summaryrefslogtreecommitdiff
path: root/SmartDeviceLinkTests/DevAPISpecs
diff options
context:
space:
mode:
authorJoel Fischer <joeljfischer@gmail.com>2021-09-24 08:53:59 -0400
committerJoel Fischer <joeljfischer@gmail.com>2021-09-24 08:53:59 -0400
commit60104522aad1c45cdd55fa0c5b73e4b369e79582 (patch)
treeef051bd14ff9f9c6a10c12378fffb7df19c0002e /SmartDeviceLinkTests/DevAPISpecs
parent7ef29ccad916ad794aa7983817a4aa3a9fc59a5e (diff)
parent4c1fe3f7b15c11763adc88b2078b609df068e031 (diff)
downloadsdl_ios-60104522aad1c45cdd55fa0c5b73e4b369e79582.tar.gz
Merge branch 'develop' into feature/issue-1898-menu-manager-refactor
# Conflicts: # SmartDeviceLink-iOS.xcodeproj/project.pbxproj # SmartDeviceLink-iOS.xcodeproj/xcshareddata/xcschemes/SmartDeviceLink-Example-Swift.xcscheme
Diffstat (limited to 'SmartDeviceLinkTests/DevAPISpecs')
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLCheckChoiceVROptionalOperationSpec.m18
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m733
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLDeleteChoicesOperationSpec.m25
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLPreloadChoicesOperationSpec.m417
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLPreloadPresentChoicesOperationSpec.m1070
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLPreloadPresentChoicesOperationUtilitiesSpec.m504
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLPresentChoiceSetOperationSpec.m549
7 files changed, 1677 insertions, 1639 deletions
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLCheckChoiceVROptionalOperationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLCheckChoiceVROptionalOperationSpec.m
index 265dad6e4..f811192a4 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLCheckChoiceVROptionalOperationSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLCheckChoiceVROptionalOperationSpec.m
@@ -17,20 +17,17 @@ describe(@"check choice VR optional operation", ^{
__block SDLCheckChoiceVROptionalOperation *testOp = nil;
__block BOOL resultVROptional = NO;
- __block BOOL hasCalledOperationCompletionHandler = NO;
__block NSError *resultError = nil;
beforeEach(^{
resultVROptional = NO;
- hasCalledOperationCompletionHandler = NO;
+ resultError = nil;
testConnectionManager = [[TestConnectionManager alloc] init];
- testOp = [[SDLCheckChoiceVROptionalOperation alloc] initWithConnectionManager:testConnectionManager];
- testOp.completionBlock = ^{
- hasCalledOperationCompletionHandler = YES;
- resultVROptional = testOp.vrOptional;
- resultError = testOp.error;
- };
+ testOp = [[SDLCheckChoiceVROptionalOperation alloc] initWithConnectionManager:testConnectionManager completionHandler:^(BOOL isVROptional, NSError * _Nullable error) {
+ resultVROptional = isVROptional;
+ resultError = error;
+ }];
});
it(@"should have priority of 'very high'", ^{
@@ -80,7 +77,6 @@ describe(@"check choice VR optional operation", ^{
});
it(@"should have called the completion handler with proper data and finish", ^{
- expect(hasCalledOperationCompletionHandler).toEventually(beTrue());
expect(resultVROptional).to(beTrue());
expect(resultError).to(beNil());
expect(@(testOp.finished)).to(equal(@YES));
@@ -99,8 +95,6 @@ describe(@"check choice VR optional operation", ^{
});
it(@"should have sent out a new request", ^{
- expect(hasCalledOperationCompletionHandler).to(beFalse());
-
expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLCreateInteractionChoiceSet class]));
SDLCreateInteractionChoiceSet *receivedRequest = testConnectionManager.receivedRequests.lastObject;
@@ -132,7 +126,6 @@ describe(@"check choice VR optional operation", ^{
});
it(@"should have called the completion handler with proper data and finish", ^{
- expect(hasCalledOperationCompletionHandler).toEventually(beTrue());
expect(resultVROptional).to(beFalse());
expect(resultError).to(beNil());
expect(@(testOp.finished)).to(equal(@YES));
@@ -151,7 +144,6 @@ describe(@"check choice VR optional operation", ^{
});
it(@"should return a failure", ^{
- expect(hasCalledOperationCompletionHandler).toEventually(beTrue());
expect(resultVROptional).to(beFalse());
expect(resultError).toNot(beNil());
});
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m
index 30c97f00a..815b1a0b9 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLChoiceSetManagerSpec.m
@@ -9,8 +9,7 @@
#import "SDLDeleteChoicesOperation.h"
#import "SDLError.h"
#import "SDLGlobals.h"
-#import "SDLPreloadChoicesOperation.h"
-#import "SDLPresentChoiceSetOperation.h"
+#import "SDLPreloadPresentChoicesOperation.h"
#import "SDLPresentKeyboardOperation.h"
#import "SDLRPCNotificationNotification.h"
#import "SDLStateMachine.h"
@@ -19,22 +18,18 @@
#import "TestConnectionManager.h"
-@interface SDLPreloadChoicesOperation()
-
-@property (copy, nonatomic, nullable) NSError *internalError;
-@property (strong, nonatomic, nullable) NSMutableArray<NSNumber *> *failedChoiceUploadIDs;
-
-@end
-
@interface SDLChoiceCell()
@property (assign, nonatomic) UInt16 choiceId;
@end
-@interface SDLPresentChoiceSetOperation()
+@interface SDLPreloadPresentChoicesOperation()
+@property (strong, nonatomic) NSMutableSet<SDLChoiceCell *> *cellsToUpload;
@property (copy, nonatomic, nullable) NSError *internalError;
+@property (copy, nonatomic) SDLUploadChoicesCompletionHandler preloadCompletionHandler;
+
@property (assign, nonatomic) UInt16 cancelId;
@property (strong, nonatomic, readwrite, nullable) SDLChoiceCell *selectedCell;
@property (strong, nonatomic, readwrite, nullable) SDLTriggerSource selectedTriggerSource;
@@ -42,9 +37,17 @@
@end
+@interface SDLDeleteChoicesOperation()
+
+@property (copy, nonatomic) SDLDeleteChoicesCompletionHandler deleteCompletionHandler;
+
+@end
+
@interface SDLCheckChoiceVROptionalOperation()
+@property (assign, nonatomic, getter=isVROptional) BOOL vrOptional;
@property (copy, nonatomic, nullable) NSError *internalError;
+@property (copy, nonatomic) SDLCheckChoiceVROptionalCompletionHandler vrOptionalCompletionHandler;
@end
@@ -52,17 +55,14 @@
@property (strong, nonatomic, readonly) SDLStateMachine *stateMachine;
@property (strong, nonatomic) NSOperationQueue *transactionQueue;
+@property (copy, nonatomic) dispatch_queue_t readWriteQueue;
@property (assign, nonatomic) UInt16 nextCancelId;
@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel;
@property (copy, nonatomic, nullable) SDLSystemContext currentSystemContext;
@property (copy, nonatomic, nullable) SDLWindowCapability *currentWindowCapability;
-@property (strong, nonatomic) NSMutableSet<SDLChoiceCell *> *preloadedMutableChoices;
-@property (strong, nonatomic, readonly) NSSet<SDLChoiceCell *> *pendingPreloadChoices;
-@property (strong, nonatomic) NSMutableSet<SDLChoiceCell *> *pendingMutablePreloadChoices;
-@property (strong, nonatomic, nullable) SDLChoiceSet *pendingPresentationSet;
-@property (strong, nonatomic, nullable) SDLAsynchronousOperation *pendingPresentOperation;
+@property (copy, nonatomic, readwrite) NSSet<SDLChoiceCell *> *preloadedChoices;
@property (assign, nonatomic, getter=isVROptional) BOOL vrOptional;
@@ -83,7 +83,13 @@ describe(@"choice set manager tests", ^{
__block SDLWindowCapability *enabledWindowCapability = nil;
__block SDLWindowCapability *disabledWindowCapability = nil;
- __block SDLWindowCapability *primaryTextOnlyCapability = nil;
+
+ __block SDLChoiceSet *testChoiceSet = nil;
+ __block SDLChoiceSet *testFailedChoiceSet = nil;
+ __block NSString *testTitle = @"test title";
+ __block id<SDLChoiceSetDelegate> choiceDelegate = nil;
+ __block id<SDLKeyboardDelegate> keyboardDelegate = nil;
+ __block SDLInteractionMode testMode = SDLInteractionModeBoth;
__block SDLChoiceCell *testCell1 = nil;
__block SDLChoiceCell *testCell2 = nil;
@@ -91,9 +97,13 @@ describe(@"choice set manager tests", ^{
__block SDLChoiceCell *testCell4 = nil;
__block SDLChoiceCell *testCell1Duplicate = nil;
__block SDLChoiceCell *testCell1Similar = nil;
- __block SDLVersion *choiceSetUniquenessActiveVersion = nil;
__block SDLArtwork *testArtwork = nil;
+ __block SDLTriggerSource resultTriggerSource = SDLTriggerSourceMenu;
+ __block SDLChoiceCell *resultChoiceCell = nil;
+ __block NSUInteger resultChoiceRow = NSUIntegerMax;
+ __block NSError *resultError = nil;
+
beforeEach(^{
testConnectionManager = [[TestConnectionManager alloc] init];
testFileManager = OCMClassMock([SDLFileManager class]);
@@ -121,11 +131,16 @@ describe(@"choice set manager tests", ^{
];
disabledWindowCapability = [[SDLWindowCapability alloc] init];
disabledWindowCapability.textFields = @[];
- primaryTextOnlyCapability = [[SDLWindowCapability alloc] init];
- primaryTextOnlyCapability.textFields = @[
- [[SDLTextField alloc] initWithName:SDLTextFieldNameMenuName characterSet:SDLCharacterSetUtf8 width:500 rows:1],
- ];
- choiceSetUniquenessActiveVersion = [[SDLVersion alloc] initWithMajor:7 minor:1 patch:0];
+
+ keyboardDelegate = OCMProtocolMock(@protocol(SDLKeyboardDelegate));
+ choiceDelegate = OCMProtocolMock(@protocol(SDLChoiceSetDelegate));
+ testChoiceSet = [[SDLChoiceSet alloc] initWithTitle:testTitle delegate:choiceDelegate choices:@[testCell1, testCell2, testCell3]];
+ testFailedChoiceSet = [[SDLChoiceSet alloc] initWithTitle:testTitle delegate:choiceDelegate choices:@[testCell1, testCell2, testCell3, testCell4]];
+
+ resultTriggerSource = SDLTriggerSourceMenu;
+ resultChoiceCell = nil;
+ resultChoiceRow = NSUIntegerMax;
+ resultError = nil;
});
it(@"should be in the correct startup state", ^{
@@ -212,12 +227,10 @@ describe(@"choice set manager tests", ^{
describe(@"after the bad vr optional response", ^{
beforeEach(^{
SDLCheckChoiceVROptionalOperation *vrOptionalOp = testManager.transactionQueue.operations.lastObject;
- vrOptionalOp.vrOptional = NO;
- vrOptionalOp.internalError = [NSError errorWithDomain:@"test" code:0 userInfo:nil];
- vrOptionalOp.completionBlock();
+ vrOptionalOp.vrOptionalCompletionHandler(NO, [NSError errorWithDomain:@"test" code:0 userInfo:nil]);
});
- it(@"should be ready", ^{
+ it(@"should be in startup error", ^{
expect(testManager.currentState).to(equal(SDLChoiceManagerStateStartupError));
});
});
@@ -225,8 +238,7 @@ describe(@"choice set manager tests", ^{
describe(@"after the vr optional response", ^{
beforeEach(^{
SDLCheckChoiceVROptionalOperation *vrOptionalOp = testManager.transactionQueue.operations.lastObject;
- vrOptionalOp.vrOptional = YES;
- vrOptionalOp.completionBlock();
+ vrOptionalOp.vrOptionalCompletionHandler(YES, nil);
});
it(@"should be ready", ^{
@@ -243,9 +255,7 @@ describe(@"choice set manager tests", ^{
expect(testManager.currentState).to(equal(SDLChoiceManagerStateShutdown));
expect(testManager.vrOptional).to(beTrue());
expect(testManager.currentHMILevel).to(equal(SDLHMILevelNone));
- expect(testManager.pendingPresentationSet).to(beNil());
- expect(testManager.preloadedMutableChoices).to(beEmpty());
- expect(testManager.pendingMutablePreloadChoices).to(beEmpty());
+ expect(testManager.preloadedChoices).to(beEmpty());
});
});
});
@@ -258,664 +268,128 @@ describe(@"choice set manager tests", ^{
describe(@"preloading choices", ^{
context(@"when some choices are already uploaded", ^{
beforeEach(^{
- testManager.preloadedMutableChoices = [NSMutableSet setWithArray:@[testCell1]];
-
+ testManager.preloadedChoices = [NSSet setWithArray:@[testCell1]];
[testManager preloadChoices:@[testCell1, testCell2, testCell3] withCompletionHandler:^(NSError * _Nullable error) {
}];
});
it(@"should properly start the preload", ^{
- expect(testManager.pendingPreloadChoices).toNot(contain(testCell1));
- expect(testManager.pendingPreloadChoices).to(contain(testCell2));
- expect(testManager.pendingPreloadChoices).to(contain(testCell3));
- expect(testManager.transactionQueue.operations.firstObject).to(beAnInstanceOf([SDLPreloadChoicesOperation class]));
+ expect(testManager.transactionQueue.operations[0]).to(beAnInstanceOf([SDLPreloadPresentChoicesOperation class]));
- SDLPreloadChoicesOperation *testOp = testManager.transactionQueue.operations.firstObject;
- [testOp finishOperation];
+ SDLPreloadPresentChoicesOperation *testOp = testManager.transactionQueue.operations[0];
+ testOp.preloadCompletionHandler([NSSet setWithArray:@[testCell1, testCell2, testCell3]], nil);
expect(testManager.preloadedChoices).to(contain(testCell1));
expect(testManager.preloadedChoices).to(contain(testCell2));
expect(testManager.preloadedChoices).to(contain(testCell3));
- expect(testManager.pendingPreloadChoices).to(haveCount(0));
- });
- });
-
- context(@"when some choices are already uploaded with duplicate titles version >= 7.1.0", ^{
- beforeEach(^{
- [SDLGlobals sharedGlobals].rpcVersion = choiceSetUniquenessActiveVersion;
- });
-
- context(@"if there are duplicate cells once you strip unused cell properties", ^{
- beforeEach(^{
- testManager.currentWindowCapability = primaryTextOnlyCapability;
- [testManager preloadChoices:@[testCell1, testCell1Similar] withCompletionHandler:^(NSError * _Nullable error) { }];
- });
-
- it(@"should update the choiceCells' unique title", ^{
- SDLPreloadChoicesOperation *testOp = testManager.transactionQueue.operations.firstObject;
- [testOp finishOperation];
- NSArray <SDLChoiceCell *> *testArrays = testManager.preloadedChoices.allObjects;
- for (SDLChoiceCell *choiceCell in testArrays) {
- if (choiceCell.secondaryText) {
- expect(choiceCell.uniqueText).to(equal("test1 (2)"));
- } else {
- expect(choiceCell.uniqueText).to(equal("test1"));
- }
- }
- expect(testManager.preloadedChoices).to(haveCount(2));
- expect(testManager.preloadedChoices).to(contain(testCell1));
- expect(testManager.preloadedChoices).to(contain(testCell1Duplicate));
- });
- });
-
- context(@"if all cell properties are used", ^{
- beforeEach(^{
- testManager.currentWindowCapability = enabledWindowCapability;
- [testManager preloadChoices:@[testCell1, testCell1Similar] withCompletionHandler:^(NSError * _Nullable error) { }];
- });
-
- it(@"should not update the choiceCells' unique title", ^{
- SDLPreloadChoicesOperation *testOp = testManager.transactionQueue.operations.firstObject;
- [testOp finishOperation];
- NSArray <SDLChoiceCell *> *testArrays = testManager.preloadedChoices.allObjects;
- for (SDLChoiceCell *choiceCell in testArrays) {
- expect(choiceCell.uniqueText).to(equal("test1"));
- }
- expect(testManager.preloadedChoices).to(haveCount(2));
- expect(testManager.preloadedChoices).to(contain(testCell1));
- expect(testManager.preloadedChoices).to(contain(testCell1Duplicate));
- });
- });
- });
-
- context(@"when some choices are already uploaded with duplicate titles version <= 7.1.0", ^{
- beforeEach(^{
- [SDLGlobals sharedGlobals].rpcVersion = [[SDLVersion alloc] initWithMajor:7 minor:0 patch:0];
- [testManager preloadChoices:@[testCell1, testCell1Similar] withCompletionHandler:^(NSError * _Nullable error) { }];
- });
-
- it(@"append a number to the unique text for choice set cells", ^{
- SDLPreloadChoicesOperation *testOp = testManager.transactionQueue.operations.firstObject;
- [testOp finishOperation];
- NSArray <SDLChoiceCell *> *testArrays = testManager.preloadedChoices.allObjects;
- for (SDLChoiceCell *choiceCell in testArrays) {
- if (choiceCell.secondaryText) {
- expect(choiceCell.uniqueText).to(equal("test1 (2)"));
- } else {
- expect(choiceCell.uniqueText).to(equal("test1"));
- }
- }
- expect(testManager.preloadedChoices).to(haveCount(2));
- expect(testManager.preloadedChoices).to(contain(testCell1));
- expect(testManager.preloadedChoices).to(contain(testCell1Duplicate));
});
});
- context(@"when some choices are already pending", ^{
+ context(@"when the manager shuts down during preloading", ^{
beforeEach(^{
- testManager.pendingMutablePreloadChoices = [NSMutableSet setWithArray:@[testCell1]];
-
[testManager preloadChoices:@[testCell1, testCell2, testCell3] withCompletionHandler:^(NSError * _Nullable error) {
+ resultError = error;
}];
});
- it(@"should properly start the preload", ^{
- expect(testManager.pendingPreloadChoices).to(contain(testCell1));
- expect(testManager.pendingPreloadChoices).to(contain(testCell2));
- expect(testManager.pendingPreloadChoices).to(contain(testCell3));
- expect(testManager.transactionQueue.operations.firstObject).to(beAnInstanceOf([SDLPreloadChoicesOperation class]));
-
- SDLPreloadChoicesOperation *testOp = testManager.transactionQueue.operations.firstObject;
- [testOp finishOperation];
-
- expect(testManager.preloadedChoices).toNot(contain(testCell1));
- expect(testManager.preloadedChoices).to(contain(testCell2));
- expect(testManager.preloadedChoices).to(contain(testCell3));
- expect(testManager.pendingPreloadChoices).to(haveCount(1));
- });
- });
-
- context(@"when the manager shuts down during preloading", ^{
- beforeEach(^{
- testManager.pendingMutablePreloadChoices = [NSMutableSet setWithArray:@[testCell1]];
-
- [testManager preloadChoices:@[testCell1, testCell2, testCell3] withCompletionHandler:^(NSError * _Nullable error) {}];
- });
-
it(@"should leave the list of pending and uploaded choice items empty when the operation finishes", ^{
- expect(testManager.pendingPreloadChoices).to(contain(testCell1));
- expect(testManager.pendingPreloadChoices).to(contain(testCell2));
- expect(testManager.pendingPreloadChoices).to(contain(testCell3));
- expect(testManager.transactionQueue.operations.firstObject).to(beAnInstanceOf([SDLPreloadChoicesOperation class]));
+ expect(testManager.transactionQueue.operations.firstObject).to(beAnInstanceOf([SDLPreloadPresentChoicesOperation class]));
[testManager.stateMachine setToState:SDLChoiceManagerStateShutdown fromOldState:nil callEnterTransition:NO];
- testManager.pendingMutablePreloadChoices = [NSMutableSet set];
- testManager.preloadedMutableChoices = [NSMutableSet set];
+ testManager.preloadedChoices = [NSMutableSet set];
- SDLPreloadChoicesOperation *testOp = testManager.transactionQueue.operations.firstObject;
+ SDLPreloadPresentChoicesOperation *testOp = testManager.transactionQueue.operations.firstObject;
[testOp finishOperation];
- expect(testManager.preloadedMutableChoices).to(beEmpty());
expect(testManager.preloadedChoices).to(beEmpty());
- expect(testManager.pendingMutablePreloadChoices).to(beEmpty());
- expect(testManager.pendingPreloadChoices).to(beEmpty());
});
});
});
describe(@"deleting choices", ^{
- context(@"used in a pending presentation", ^{
- __block SDLPresentChoiceSetOperation *pendingPresentOp = nil;
- __block id<SDLChoiceSetDelegate> choiceDelegate = nil;
-
- beforeEach(^{
- choiceDelegate = OCMProtocolMock(@protocol(SDLChoiceSetDelegate));
- pendingPresentOp = OCMClassMock([SDLPresentChoiceSetOperation class]);
- OCMStub(pendingPresentOp.choiceSet.choices).andReturn([NSSet setWithArray:@[testCell1]]);
- testManager.pendingPresentOperation = pendingPresentOp;
- testManager.pendingPresentationSet = [[SDLChoiceSet alloc] initWithTitle:@"Test" delegate:choiceDelegate choices:@[testCell1]];
-
- testManager.preloadedMutableChoices = [NSMutableSet setWithObject:testCell1];
-
- [testManager deleteChoices:@[testCell1, testCell2, testCell3]];
- });
-
- it(@"should properly start the deletion", ^{
- expect(testManager.transactionQueue.operations.lastObject).to(beAnInstanceOf([SDLDeleteChoicesOperation class]));
- expect(testManager.pendingPresentationSet).to(beNil());
- OCMVerify([pendingPresentOp cancel]);
- OCMVerify([choiceDelegate choiceSet:[OCMArg any] didReceiveError:[OCMArg any]]);
-
- testManager.transactionQueue.operations.lastObject.completionBlock();
- expect(testManager.preloadedChoices).to(beEmpty());
- });
- });
-
context(@"used in pending preloads", ^{
- __block SDLPreloadChoicesOperation *pendingPreloadOp = nil;
-
beforeEach(^{
- pendingPreloadOp = [[SDLPreloadChoicesOperation alloc] init];
-
- [testManager.transactionQueue addOperation:pendingPreloadOp];
-
- testManager.pendingMutablePreloadChoices = [NSMutableSet setWithObject:testCell1];
+ [testManager preloadChoices:@[testCell1, testCell2, testCell3, testCell4] withCompletionHandler:^(NSError * _Nullable error) {}];
[testManager deleteChoices:@[testCell1, testCell2, testCell3]];
});
- it(@"should properly start the deletion", ^{
- expect(testManager.pendingPreloadChoices).to(beEmpty());
- expect(testManager.transactionQueue.operationCount).to(equal(1)); // No delete operation
+ it(@"should preload the choices, then delete them", ^{
+ expect(testManager.transactionQueue.operationCount).to(equal(2));
+ expect(testManager.transactionQueue.operations[0]).to(beAnInstanceOf(SDLPreloadPresentChoicesOperation.class));
+ expect(testManager.transactionQueue.operations[1]).to(beAnInstanceOf(SDLDeleteChoicesOperation.class));
});
});
context(@"when the manager shuts down during deletion", ^{
- __block SDLPresentChoiceSetOperation *pendingPresentOp = nil;
- __block id<SDLChoiceSetDelegate> choiceDelegate = nil;
-
beforeEach(^{
- choiceDelegate = OCMProtocolMock(@protocol(SDLChoiceSetDelegate));
- pendingPresentOp = OCMClassMock([SDLPresentChoiceSetOperation class]);
- OCMStub(pendingPresentOp.choiceSet.choices).andReturn([NSSet setWithArray:@[testCell1]]);
- testManager.pendingPresentOperation = pendingPresentOp;
- testManager.pendingPresentationSet = [[SDLChoiceSet alloc] initWithTitle:@"Test" delegate:choiceDelegate choices:@[testCell1]];
- testManager.preloadedMutableChoices = [NSMutableSet setWithObject:testCell1];
+ testManager.preloadedChoices = [NSSet setWithArray:@[testCell1, testCell2, testCell3]];
+ [testManager deleteChoices:@[testCell1, testCell2]];
- [testManager deleteChoices:@[testCell1, testCell2, testCell3]];
+ [SDLGlobals runSyncOnSerialSubQueue:testManager.readWriteQueue block:^{
+ [testManager.stateMachine setToState:SDLChoiceManagerStateShutdown fromOldState:SDLChoiceManagerStateReady callEnterTransition:YES];
+ }];
});
it(@"should leave the list of pending and uploaded choice items empty when the operation finishes", ^{
- expect(testManager.transactionQueue.operations.lastObject).to(beAnInstanceOf([SDLDeleteChoicesOperation class]));
- expect(testManager.pendingPresentationSet).to(beNil());
- OCMVerify([pendingPresentOp cancel]);
- OCMVerify([choiceDelegate choiceSet:[OCMArg any] didReceiveError:[OCMArg any]]);
-
- [testManager.stateMachine setToState:SDLChoiceManagerStateShutdown fromOldState:nil callEnterTransition:NO];
- testManager.pendingMutablePreloadChoices = [NSMutableSet set];
- testManager.preloadedMutableChoices = [NSMutableSet set];
-
- testManager.transactionQueue.operations.lastObject.completionBlock();
-
- expect(testManager.preloadedMutableChoices).to(beEmpty());
+ expect(testManager.transactionQueue.operationCount).to(equal(0));
expect(testManager.preloadedChoices).to(beEmpty());
- expect(testManager.pendingMutablePreloadChoices).to(beEmpty());
- expect(testManager.pendingPreloadChoices).to(beEmpty());
});
});
});
describe(@"presenting a choice set", ^{
- __block SDLChoiceSet *testChoiceSet = nil;
- __block SDLChoiceSet *testFailedChoiceSet = nil;
- __block NSString *testTitle = @"test title";
- __block id<SDLChoiceSetDelegate> choiceDelegate = nil;
- __block id<SDLKeyboardDelegate> keyboardDelegate = nil;
- __block SDLInteractionMode testMode = SDLInteractionModeBoth;
- __block SDLPresentKeyboardOperation *pendingPresentOp = nil;
- __block id strickMockOperationQueue = nil;
- __block SDLChoiceCell *testSelectedCell = nil;
- __block NSError *testError = nil;
- NSUInteger testSelectedCellRow = 1;
-
- beforeEach(^{
- keyboardDelegate = OCMProtocolMock(@protocol(SDLKeyboardDelegate));
- choiceDelegate = OCMProtocolMock(@protocol(SDLChoiceSetDelegate));
- testChoiceSet = [[SDLChoiceSet alloc] initWithTitle:testTitle delegate:choiceDelegate choices:@[testCell1, testCell2, testCell3]];
- testFailedChoiceSet = [[SDLChoiceSet alloc] initWithTitle:testTitle delegate:choiceDelegate choices:@[testCell1, testCell2, testCell3, testCell4]];
- testSelectedCell = testChoiceSet.choices[1];
- testError = [NSError sdl_choiceSetManager_failedToCreateMenuItems];
-
- pendingPresentOp = OCMClassMock([SDLPresentKeyboardOperation class]);
- testManager.pendingPresentOperation = pendingPresentOp;
- testManager.pendingPresentationSet = [[SDLChoiceSet alloc] init];
-
- strickMockOperationQueue = OCMStrictClassMock([NSOperationQueue class]);
- [strickMockOperationQueue setExpectationOrderMatters:YES];
- testManager.transactionQueue = strickMockOperationQueue;
- });
-
- context(@"searchable", ^{
- it(@"should notify the choice delegate when a choice item is selected", ^{
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- expect(testManager.pendingPresentationSet).to(equal(testChoiceSet));
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPresentChoiceSetOperation *presentChoicesOperation = (SDLPresentChoiceSetOperation *)value;
- presentChoicesOperation.selectedCell = testSelectedCell;
- presentChoicesOperation.selectedTriggerSource = testMode;
- presentChoicesOperation.selectedCellRow = testSelectedCellRow;
- presentChoicesOperation.internalError = nil;
- presentChoicesOperation.completionBlock();
- return [value isKindOfClass:[SDLPresentChoiceSetOperation class]];
- }]]);
- OCMExpect([choiceDelegate choiceSet:testChoiceSet didSelectChoice:testSelectedCell withSource:testMode atRowIndex:testSelectedCellRow]);
-
- [testManager presentChoiceSet:testChoiceSet mode:testMode withKeyboardDelegate:keyboardDelegate];
-
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
- OCMVerifyAllWithDelay(choiceDelegate, 0.5);
-
- expect(testManager.pendingPresentationSet).to(beNil());
- expect(testManager.pendingPresentOperation).to(beNil());
-
- expect(testManager.preloadedMutableChoices.count).to(equal(3));
- expect(testManager.preloadedMutableChoices).to(contain(testChoiceSet.choices[0]));
- expect(testManager.preloadedMutableChoices).to(contain(testChoiceSet.choices[1]));
- expect(testManager.preloadedMutableChoices).to(contain(testChoiceSet.choices[2]));
- expect(testManager.pendingMutablePreloadChoices).to(beEmpty());
- });
-
- it(@"should notify the choice delegate if an error occured during presentation", ^{
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- expect(testManager.pendingPresentationSet).to(equal(testChoiceSet));
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPresentChoiceSetOperation *presentChoicesOperation = (SDLPresentChoiceSetOperation *)value;
- presentChoicesOperation.internalError = testError;
- presentChoicesOperation.completionBlock();
- return [value isKindOfClass:[SDLPresentChoiceSetOperation class]];
- }]]);
- OCMExpect([choiceDelegate choiceSet:[OCMArg any] didReceiveError:testError]);
-
- [testManager presentChoiceSet:testChoiceSet mode:testMode withKeyboardDelegate:keyboardDelegate];
-
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
- OCMVerifyAllWithDelay(choiceDelegate, 0.5);
-
- expect(testManager.pendingPresentationSet).to(beNil());
- expect(testManager.pendingPresentOperation).to(beNil());
-
- expect(testManager.preloadedMutableChoices.count).to(equal(3));
- expect(testManager.preloadedMutableChoices).to(contain(testChoiceSet.choices[0]));
- expect(testManager.preloadedMutableChoices).to(contain(testChoiceSet.choices[1]));
- expect(testManager.preloadedMutableChoices).to(contain(testChoiceSet.choices[2]));
- expect(testManager.pendingMutablePreloadChoices).to(beEmpty());
- });
-
- it(@"should not add a choice item that fails to the list of preloaded choices", ^{
- NSMutableDictionary<SDLRPCRequest *, NSError *> *testErrors = [NSMutableDictionary dictionary];
- SDLCreateInteractionChoiceSet *failedChoiceSet = [[SDLCreateInteractionChoiceSet alloc] initWithId:0 choiceSet:@[[[SDLChoice alloc] initWithId:1 menuName:@"1" vrCommands:nil]]];
- testErrors[failedChoiceSet] = [NSError sdl_choiceSetManager_choiceUploadFailed:[NSDictionary dictionary]];
- NSError *testInternalError = [NSError sdl_choiceSetManager_choiceUploadFailed:testErrors];
-
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- expect(testManager.pendingMutablePreloadChoices.count).to(equal(4));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[0]));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[1]));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[2]));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[3]));
- preloadChoicesOperation.internalError = testInternalError;
- preloadChoicesOperation.failedChoiceUploadIDs = [[NSMutableArray alloc] initWithArray:(@[@1])];
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMReject([strickMockOperationQueue addOperation:[OCMArg isKindOfClass:SDLPresentChoiceSetOperation.class]]);
- OCMExpect([choiceDelegate choiceSet:[OCMArg any] didReceiveError:testInternalError]);
-
- [testManager presentChoiceSet:testFailedChoiceSet mode:testMode withKeyboardDelegate:keyboardDelegate];
-
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
- OCMVerifyAllWithDelay(choiceDelegate, 0.5);
-
- expect(testManager.pendingPresentationSet).toNot(beNil());
- expect(testManager.pendingPresentOperation).toNot(beNil());
-
- expect(testManager.preloadedMutableChoices.count).to(equal(3));
- expect(testManager.preloadedMutableChoices).toNot(contain(testFailedChoiceSet.choices[0]));
- expect(testManager.preloadedMutableChoices).to(contain(testFailedChoiceSet.choices[1]));
- expect(testManager.preloadedMutableChoices).to(contain(testFailedChoiceSet.choices[2]));
- expect(testManager.preloadedMutableChoices).to(contain(testFailedChoiceSet.choices[3]));
-
- expect(testManager.pendingMutablePreloadChoices).to(beEmpty());
- });
-
- it(@"should not add any of choice items if they all fail to upload to the list of preloaded choices", ^{
- NSMutableDictionary<SDLRPCRequest *, NSError *> *testErrors = [NSMutableDictionary dictionary];
- SDLCreateInteractionChoiceSet *failedChoiceSet1 = [[SDLCreateInteractionChoiceSet alloc] initWithId:0 choiceSet:@[[[SDLChoice alloc] initWithId:1 menuName:@"1" vrCommands:nil]]];
- SDLCreateInteractionChoiceSet *failedChoiceSet2 = [[SDLCreateInteractionChoiceSet alloc] initWithId:0 choiceSet:@[[[SDLChoice alloc] initWithId:2 menuName:@"2" vrCommands:nil]]];
- SDLCreateInteractionChoiceSet *failedChoiceSet3 = [[SDLCreateInteractionChoiceSet alloc] initWithId:0 choiceSet:@[[[SDLChoice alloc] initWithId:3 menuName:@"3" vrCommands:nil]]];
- SDLCreateInteractionChoiceSet *failedChoiceSet4 = [[SDLCreateInteractionChoiceSet alloc] initWithId:0 choiceSet:@[[[SDLChoice alloc] initWithId:4 menuName:@"4" vrCommands:nil]]];
- testErrors[failedChoiceSet1] = [NSError sdl_choiceSetManager_choiceUploadFailed:[NSDictionary dictionary]];
- testErrors[failedChoiceSet2] = [NSError sdl_choiceSetManager_choiceUploadFailed:[NSDictionary dictionary]];
- testErrors[failedChoiceSet3] = [NSError sdl_choiceSetManager_choiceUploadFailed:[NSDictionary dictionary]];
- testErrors[failedChoiceSet4] = [NSError sdl_choiceSetManager_choiceUploadFailed:[NSDictionary dictionary]];
- NSError *testInternalError = [NSError sdl_choiceSetManager_choiceUploadFailed:testErrors];
-
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- expect(testManager.pendingMutablePreloadChoices.count).to(equal(4));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[0]));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[1]));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[2]));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[3]));
- preloadChoicesOperation.internalError = testInternalError;
- preloadChoicesOperation.failedChoiceUploadIDs = [[NSMutableArray alloc] initWithArray:(@[@1, @2, @3, @4])];
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMReject([strickMockOperationQueue addOperation:[OCMArg isKindOfClass:SDLPresentChoiceSetOperation.class]]);
- OCMExpect([choiceDelegate choiceSet:[OCMArg any] didReceiveError:testInternalError]);
-
- [testManager presentChoiceSet:testFailedChoiceSet mode:testMode withKeyboardDelegate:keyboardDelegate];
-
- OCMVerifyAllWithDelay(strickMockOperationQueue, 1.0);
- OCMVerifyAllWithDelay(choiceDelegate, 0.5);
-
- expect(testManager.pendingPresentationSet).toNot(beNil());
- expect(testManager.pendingPresentOperation).toNot(beNil());
-
- expect(testManager.preloadedMutableChoices).to(beEmpty());
- expect(testManager.pendingMutablePreloadChoices).to(beEmpty());
- });
- });
-
- it(@"should skip preloading the choices if all choice items have already been uploaded", ^{
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- expect(testManager.pendingMutablePreloadChoices.count).to(equal(3));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testChoiceSet.choices[0]));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testChoiceSet.choices[1]));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testChoiceSet.choices[2]));
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPresentChoiceSetOperation *presentChoicesOperation = (SDLPresentChoiceSetOperation *)value;
- presentChoicesOperation.selectedCell = testSelectedCell;
- presentChoicesOperation.selectedTriggerSource = testMode;
- presentChoicesOperation.selectedCellRow = testSelectedCellRow;
- presentChoicesOperation.internalError = nil;
- presentChoicesOperation.completionBlock();
- return [value isKindOfClass:[SDLPresentChoiceSetOperation class]];
- }]]);
- OCMExpect([choiceDelegate choiceSet:testChoiceSet didSelectChoice:testSelectedCell withSource:testMode atRowIndex:testSelectedCellRow]);
-
- [testManager presentChoiceSet:testChoiceSet mode:testMode withKeyboardDelegate:keyboardDelegate];
-
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
- OCMVerifyAllWithDelay(choiceDelegate, 0.5);
-
- expect(testManager.pendingPresentationSet).to(beNil());
- expect(testManager.pendingPresentOperation).to(beNil());
-
- expect(testManager.preloadedMutableChoices.count).to(equal(3));
- expect(testManager.pendingMutablePreloadChoices).to(beEmpty());
-
- // Present the exact same choices again
- OCMReject([strickMockOperationQueue addOperation:[OCMArg isKindOfClass:SDLPreloadChoicesOperation.class]]);
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPresentChoiceSetOperation *presentChoicesOperation = (SDLPresentChoiceSetOperation *)value;
- presentChoicesOperation.selectedCell = testSelectedCell;
- presentChoicesOperation.selectedTriggerSource = testMode;
- presentChoicesOperation.selectedCellRow = testSelectedCellRow;
- presentChoicesOperation.internalError = nil;
- presentChoicesOperation.completionBlock();
- return [value isKindOfClass:[SDLPresentChoiceSetOperation class]];
- }]]);
- OCMExpect([choiceDelegate choiceSet:testChoiceSet didSelectChoice:testSelectedCell withSource:testMode atRowIndex:testSelectedCellRow]);
-
- [testManager presentChoiceSet:testChoiceSet mode:testMode withKeyboardDelegate:keyboardDelegate];
-
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
- OCMVerifyAllWithDelay(choiceDelegate, 0.5);
- });
-
- it(@"should upload choices that failed to upload in previous presentations", ^{
- NSMutableDictionary<SDLRPCRequest *, NSError *> *testErrors = [NSMutableDictionary dictionary];
- SDLCreateInteractionChoiceSet *failedChoiceSet = [[SDLCreateInteractionChoiceSet alloc] initWithId:0 choiceSet:@[[[SDLChoice alloc] initWithId:1 menuName:@"1" vrCommands:nil]]];
- testErrors[failedChoiceSet] = [NSError sdl_choiceSetManager_choiceUploadFailed:[NSDictionary dictionary]];
- NSError *testInternalError = [NSError sdl_choiceSetManager_choiceUploadFailed:testErrors];
-
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- expect(testManager.pendingMutablePreloadChoices.count).to(equal(4));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[0]));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[1]));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[2]));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[3]));
- expect(testManager.pendingPresentationSet).to(equal(testFailedChoiceSet));
- preloadChoicesOperation.internalError = testInternalError;
- preloadChoicesOperation.failedChoiceUploadIDs = [[NSMutableArray alloc] initWithArray:(@[@1])];
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMExpect([choiceDelegate choiceSet:[OCMArg any] didReceiveError:testInternalError]);
-
- [testManager presentChoiceSet:testFailedChoiceSet mode:testMode withKeyboardDelegate:keyboardDelegate];
-
- OCMVerifyAllWithDelay(strickMockOperationQueue, 1.0);
- OCMVerifyAllWithDelay(choiceDelegate, 0.5);
-
- expect(testManager.pendingPresentationSet).toNot(beNil());
- expect(testManager.pendingPresentOperation).toNot(beNil());
-
- expect(testManager.preloadedMutableChoices.count).to(equal(3));
- expect(testManager.preloadedMutableChoices).toNot(contain(testFailedChoiceSet.choices[0]));
- expect(testManager.preloadedMutableChoices).to(contain(testFailedChoiceSet.choices[1]));
- expect(testManager.preloadedMutableChoices).to(contain(testFailedChoiceSet.choices[2]));
- expect(testManager.preloadedMutableChoices).to(contain(testFailedChoiceSet.choices[3]));
- expect(testManager.pendingMutablePreloadChoices).to(beEmpty());
-
- // Present the exact same choices again
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- expect(testManager.pendingMutablePreloadChoices.count).to(equal(1));
- expect(testManager.pendingMutablePreloadChoices).to(contain(testFailedChoiceSet.choices[0]));
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPresentChoiceSetOperation *presentChoicesOperation = (SDLPresentChoiceSetOperation *)value;
- presentChoicesOperation.selectedCell = testSelectedCell;
- presentChoicesOperation.selectedTriggerSource = testMode;
- presentChoicesOperation.selectedCellRow = testSelectedCellRow;
- presentChoicesOperation.internalError = nil;
- presentChoicesOperation.completionBlock();
- return [value isKindOfClass:[SDLPresentChoiceSetOperation class]];
- }]]);
- OCMExpect([choiceDelegate choiceSet:testChoiceSet didSelectChoice:testSelectedCell withSource:testMode atRowIndex:testSelectedCellRow]);
-
- [testManager presentChoiceSet:testChoiceSet mode:testMode withKeyboardDelegate:keyboardDelegate];
-
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
- OCMVerifyAllWithDelay(choiceDelegate, 0.5);
-
- expect(testManager.pendingPresentationSet).to(beNil());
- expect(testManager.pendingPresentOperation).to(beNil());
-
- expect(testManager.preloadedMutableChoices.count).to(equal(4));
- expect(testManager.preloadedMutableChoices).to(contain(testFailedChoiceSet.choices[0]));
- expect(testManager.preloadedMutableChoices).to(contain(testFailedChoiceSet.choices[1]));
- expect(testManager.preloadedMutableChoices).to(contain(testFailedChoiceSet.choices[2]));
- expect(testManager.preloadedMutableChoices).to(contain(testFailedChoiceSet.choices[3]));
- expect(testManager.pendingMutablePreloadChoices).to(beEmpty());
- });
-
it(@"should not present choices if the manager shuts down after the choices are uploaded but before presentation", ^{
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- expect(testManager.pendingPresentationSet).to(equal(testChoiceSet));
- [preloadChoicesOperation finishOperation];
- [testManager.stateMachine setToState:SDLChoiceManagerStateShutdown fromOldState:nil callEnterTransition:NO];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMReject([strickMockOperationQueue addOperation:[OCMArg isKindOfClass:SDLPresentChoiceSetOperation.class]]);
-
+ OCMExpect([choiceDelegate choiceSet:[OCMArg any] didReceiveError:[OCMArg isNotNil]]);
[testManager presentChoiceSet:testChoiceSet mode:testMode withKeyboardDelegate:nil];
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
+ SDLPreloadPresentChoicesOperation *preload = (SDLPreloadPresentChoicesOperation *)testManager.transactionQueue.operations[0];
+ preload.loadedCells = [NSSet setWithArray:testChoiceSet.choices];
- expect(testManager.pendingPresentOperation).toEventually(beNil());
- expect(testManager.pendingPresentationSet).toEventually(beNil());
- });
-
- context(@"non-searchable", ^{
- it(@"should notify the choice delegate when a choice item is selected", ^{
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- expect(testManager.pendingPresentationSet).to(equal(testChoiceSet));
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPresentChoiceSetOperation *presentChoicesOperation = (SDLPresentChoiceSetOperation *)value;
- presentChoicesOperation.selectedCell = testSelectedCell;
- presentChoicesOperation.selectedTriggerSource = testMode;
- presentChoicesOperation.selectedCellRow = testSelectedCellRow;
- presentChoicesOperation.internalError = nil;
- presentChoicesOperation.completionBlock();
- return [value isKindOfClass:[SDLPresentChoiceSetOperation class]];
- }]]);
- OCMExpect([choiceDelegate choiceSet:testChoiceSet didSelectChoice:testSelectedCell withSource:testMode atRowIndex:testSelectedCellRow]);
-
- [testManager presentChoiceSet:testChoiceSet mode:testMode withKeyboardDelegate:nil];
-
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
- OCMVerifyAllWithDelay(choiceDelegate, 0.5);
-
- expect(testManager.pendingPresentationSet).to(beNil());
- expect(testManager.pendingPresentOperation).to(beNil());
- });
+ [SDLGlobals runSyncOnSerialSubQueue:testManager.readWriteQueue block:^{
+ [testManager.stateMachine setToState:SDLChoiceManagerStateShutdown fromOldState:SDLChoiceManagerStateReady callEnterTransition:YES];
+ }];
+ [preload finishOperation];
- it(@"should notify the choice delegate if an error occured during presentation", ^{
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- expect(testManager.pendingPresentationSet).to(equal(testChoiceSet));
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPresentChoiceSetOperation *presentChoicesOperation = (SDLPresentChoiceSetOperation *)value;
- presentChoicesOperation.internalError = testError;
- presentChoicesOperation.completionBlock();
- return [value isKindOfClass:[SDLPresentChoiceSetOperation class]];
- }]]);
- OCMExpect([choiceDelegate choiceSet:[OCMArg any] didReceiveError:testError]);
-
- [testManager presentChoiceSet:testChoiceSet mode:testMode withKeyboardDelegate:nil];
-
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
- OCMVerifyAllWithDelay(choiceDelegate, 0.5);
-
- expect(testManager.pendingPresentationSet).to(beNil());
- expect(testManager.pendingPresentOperation).to(beNil());
- });
+ expect(testManager.preloadedChoices).to(beEmpty());
+ expect(testManager.transactionQueue.operationCount).to(equal(0));
});
describe(@"when the manager shuts down during presentation", ^{
- __block SDLPresentChoiceSetOperation *presentChoicesOperation = nil;
-
it(@"should leave the list of pending and uploaded choice items empty when the operation finishes", ^{
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- expect(testManager.pendingPresentationSet).to(equal(testChoiceSet));
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- presentChoicesOperation = (SDLPresentChoiceSetOperation *)value;
- presentChoicesOperation.internalError = nil;
- testManager.pendingMutablePreloadChoices = [NSMutableSet set];
- testManager.preloadedMutableChoices = [NSMutableSet set];
-
- [testManager.stateMachine setToState:SDLChoiceManagerStateShutdown fromOldState:nil callEnterTransition:NO];
- presentChoicesOperation.completionBlock();
- return [value isKindOfClass:[SDLPresentChoiceSetOperation class]];
- }]]);
-
[testManager presentChoiceSet:testChoiceSet mode:testMode withKeyboardDelegate:keyboardDelegate];
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
- expect(testManager.preloadedMutableChoices).to(beEmpty());
+ SDLPreloadPresentChoicesOperation *preloadChoicesOperation = (SDLPreloadPresentChoicesOperation *)testManager.transactionQueue.operations.firstObject;
+ [testManager.stateMachine setToState:SDLChoiceManagerStateShutdown fromOldState:nil callEnterTransition:NO];
+ [preloadChoicesOperation finishOperation];
+
expect(testManager.preloadedChoices).to(beEmpty());
- expect(testManager.pendingMutablePreloadChoices).to(beEmpty());
- expect(testManager.pendingPreloadChoices).to(beEmpty());
});
});
-
- afterEach(^{
- [strickMockOperationQueue stopMocking];
- });
});
describe(@"presenting a keyboard", ^{
- __block SDLPresentChoiceSetOperation *pendingPresentOp = nil;
__block NSString *testInitialText = @"Test text";
__block id<SDLKeyboardDelegate> testKeyboardDelegate = nil;
beforeEach(^{
testKeyboardDelegate = OCMProtocolMock(@protocol(SDLKeyboardDelegate));
-
- pendingPresentOp = OCMClassMock([SDLPresentChoiceSetOperation class]);
- testManager.pendingPresentOperation = pendingPresentOp;
- testManager.pendingPresentationSet = [[SDLChoiceSet alloc] init];
});
it(@"should return a cancelID and should properly start the keyboard presentation with presentKeyboardWithInitialText:keyboardDelegate:", ^{
NSNumber *cancelID = [testManager presentKeyboardWithInitialText:testInitialText delegate:testKeyboardDelegate];
expect(cancelID).toNot(beNil());
- OCMVerify([pendingPresentOp cancel]);
expect(testManager.transactionQueue.operations).to(haveCount(1));
- expect(testManager.pendingPresentOperation).to(beAnInstanceOf([SDLPresentKeyboardOperation class]));
+ expect( testManager.transactionQueue.operations[0]).to(beAnInstanceOf([SDLPresentKeyboardOperation class]));
});
- it(@"should return nil and should not start the keyboard presentation if the the keyboard can not be sent to Core", ^{
+ it(@"should return nil and should not start the keyboard presentation if the keyboard can not be sent to Core", ^{
[testManager.stateMachine setToState:SDLChoiceManagerStateCheckingVoiceOptional fromOldState:SDLChoiceManagerStateShutdown callEnterTransition:NO];
NSNumber *cancelID = [testManager presentKeyboardWithInitialText:testInitialText delegate:testKeyboardDelegate];
expect(cancelID).to(beNil());
- OCMReject([pendingPresentOp cancel]);
expect(testManager.transactionQueue.operations).to(haveCount(0));
- expect(testManager.pendingPresentOperation).toNot(beAnInstanceOf([SDLPresentKeyboardOperation class]));
});
});
@@ -923,7 +397,6 @@ describe(@"choice set manager tests", ^{
__block SDLChoiceSet *testChoiceSet = nil;
__block SDLChoiceSet *testChoiceSet2 = nil;
__block id<SDLChoiceSetDelegate> testChoiceDelegate = nil;
- __block id strickMockOperationQueue = nil;
beforeEach(^{
testChoiceDelegate = OCMProtocolMock(@protocol(SDLChoiceSetDelegate));
@@ -931,67 +404,29 @@ describe(@"choice set manager tests", ^{
testChoiceSet2 = [[SDLChoiceSet alloc] initWithTitle:@"choice set 2" delegate:testChoiceDelegate choices:@[testCell2]];
testManager = [[SDLChoiceSetManager alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager systemCapabilityManager:testSystemCapabilityManager];
[testManager.stateMachine setToState:SDLChoiceManagerStateReady fromOldState:SDLChoiceManagerStateCheckingVoiceOptional callEnterTransition:NO];
- strickMockOperationQueue = OCMStrictClassMock([NSOperationQueue class]);
- testManager.transactionQueue = strickMockOperationQueue;
});
it(@"should set the first cancelID correctly", ^{
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
-
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPresentChoiceSetOperation *presentChoicesOperation = (SDLPresentChoiceSetOperation *)value;
- expect(@(presentChoicesOperation.cancelId)).to(equal(101));
- presentChoicesOperation.completionBlock();
- return [value isKindOfClass:[SDLPresentChoiceSetOperation class]];
- }]]);
-
[testManager presentChoiceSet:testChoiceSet mode:SDLInteractionModeBoth withKeyboardDelegate:nil];
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
+ SDLPreloadPresentChoicesOperation *preloadChoicesOperation = (SDLPreloadPresentChoicesOperation *)testManager.transactionQueue.operations[0];
+ expect(@(preloadChoicesOperation.cancelId)).to(equal(101));
});
it(@"should reset the cancelID correctly once the max has been reached", ^{
- testManager.nextCancelId = 200; // set the max cancelID
-
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPresentChoiceSetOperation *presentChoicesOperation = (SDLPresentChoiceSetOperation *)value;
- expect(@(presentChoicesOperation.cancelId)).to(equal(200));
- presentChoicesOperation.completionBlock();
- return [value isKindOfClass:[SDLPresentChoiceSetOperation class]];
- }]]);
+ testManager.nextCancelId = 200;
[testManager presentChoiceSet:testChoiceSet mode:SDLInteractionModeBoth withKeyboardDelegate:nil];
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
-
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPreloadChoicesOperation *preloadChoicesOperation = (SDLPreloadChoicesOperation *)value;
- [preloadChoicesOperation finishOperation];
- return [value isKindOfClass:[SDLPreloadChoicesOperation class]];
- }]]);
- OCMExpect([strickMockOperationQueue addOperation:[OCMArg checkWithBlock:^BOOL(id value) {
- SDLPresentChoiceSetOperation *presentChoicesOperation = (SDLPresentChoiceSetOperation *)value;
- expect(@(presentChoicesOperation.cancelId)).to(equal(101));
- presentChoicesOperation.completionBlock();
- return [value isKindOfClass:[SDLPresentChoiceSetOperation class]];
- }]]);
+ SDLPreloadPresentChoicesOperation *presentChoicesOperation = testManager.transactionQueue.operations[0];
+ expect(@(presentChoicesOperation.cancelId)).to(equal(200));
[testManager presentChoiceSet:testChoiceSet2 mode:SDLInteractionModeBoth withKeyboardDelegate:nil];
- OCMVerifyAllWithDelay(strickMockOperationQueue, 0.5);
- });
+ [NSThread sleepForTimeInterval:0.5];
- afterEach(^{
- [strickMockOperationQueue stopMocking];
+ SDLPreloadPresentChoicesOperation *presentChoicesOperation2 = (SDLPreloadPresentChoicesOperation *)testManager.transactionQueue.operations[1];
+ expect(@(presentChoicesOperation2.cancelId)).to(equal(101));
});
});
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLDeleteChoicesOperationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLDeleteChoicesOperationSpec.m
index 2996da282..adf5632a6 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLDeleteChoicesOperationSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLDeleteChoicesOperationSpec.m
@@ -14,20 +14,23 @@ describe(@"delete choices operation", ^{
__block TestConnectionManager *testConnectionManager = nil;
__block SDLDeleteChoicesOperation *testOp = nil;
__block NSSet<SDLChoiceCell *> *testCellsToDelete = nil;
+ __block NSSet<SDLChoiceCell *> *testLoadedCells = nil;
- __block BOOL hasCalledOperationCompletionHandler = NO;
__block NSError *resultError = nil;
+ __block NSSet<SDLChoiceCell *> *resultLoadedCells;
beforeEach(^{
- hasCalledOperationCompletionHandler = NO;
-
testConnectionManager = [[TestConnectionManager alloc] init];
testCellsToDelete = [NSSet setWithArray:@[[[SDLChoiceCell alloc] initWithText:@"Text"], [[SDLChoiceCell alloc] initWithText:@"Text 2"]]];
- testOp = [[SDLDeleteChoicesOperation alloc] initWithConnectionManager:testConnectionManager cellsToDelete:testCellsToDelete];
- testOp.completionBlock = ^{
- hasCalledOperationCompletionHandler = YES;
- resultError = testOp.error;
- };
+ testLoadedCells = testCellsToDelete;
+
+ resultError = nil;
+ resultLoadedCells = nil;
+
+ testOp = [[SDLDeleteChoicesOperation alloc] initWithConnectionManager:testConnectionManager cellsToDelete:testCellsToDelete loadedCells:testLoadedCells completionHandler:^(NSSet<SDLChoiceCell *> * _Nonnull updatedLoadedCells, NSError * _Nullable error) {
+ resultLoadedCells = updatedLoadedCells;
+ resultError = error;
+ }];
});
it(@"should have priority of 'normal'", ^{
@@ -56,7 +59,7 @@ describe(@"delete choices operation", ^{
});
it(@"should finish with success", ^{
- expect(hasCalledOperationCompletionHandler).toEventually(beTrue());
+ expect(resultLoadedCells).toEventuallyNot(beNil());
expect(resultError).to(beNil());
});
});
@@ -66,8 +69,8 @@ describe(@"delete choices operation", ^{
[testConnectionManager respondToLastMultipleRequestsWithSuccess:NO];
});
- it(@"should finish with success", ^{
- expect(hasCalledOperationCompletionHandler).toEventually(beTrue());
+ it(@"should finish with a failure", ^{
+ expect(resultLoadedCells).toEventuallyNot(beNil());
expect(resultError).toNot(beNil());
});
});
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLPreloadChoicesOperationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLPreloadChoicesOperationSpec.m
deleted file mode 100644
index fc6fdfe00..000000000
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLPreloadChoicesOperationSpec.m
+++ /dev/null
@@ -1,417 +0,0 @@
-#import <Quick/Quick.h>
-#import <Nimble/Nimble.h>
-#import <OCMock/OCMock.h>
-
-#import "SDLPreloadChoicesOperation.h"
-
-#import "SDLChoice.h"
-#import "SDLChoiceCell.h"
-#import "SDLCreateInteractionChoiceSet.h"
-#import "SDLDisplayType.h"
-#import "SDLFileManager.h"
-#import "SDLImageField.h"
-#import "SDLImageFieldName.h"
-#import "SDLTextField.h"
-#import "SDLTextFieldName.h"
-#import "SDLWindowCapability.h"
-#import "TestConnectionManager.h"
-
-@interface SDLPreloadChoicesOperation()
-
-@property (strong, nonatomic, nullable) NSMutableArray<NSNumber *> *failedChoiceUploadIDs;
-
-@end
-
-@interface SDLChoiceCell()
-
-@property (assign, nonatomic) UInt16 choiceId;
-
-@end
-
-QuickSpecBegin(SDLPreloadChoicesOperationSpec)
-
-describe(@"a preload choices operation", ^{
- __block TestConnectionManager *testConnectionManager = nil;
- __block SDLFileManager *testFileManager = nil;
- __block SDLPreloadChoicesOperation *testOp = nil;
- __block NSString *testDisplayName = @"SDL_GENERIC";
-
- __block NSData *cellArtData = [@"testart" dataUsingEncoding:NSUTF8StringEncoding];
- __block NSData *cellArtData2 = [@"testart2" dataUsingEncoding:NSUTF8StringEncoding];
-
- __block BOOL hasCalledOperationCompletionHandler = NO;
- __block NSError *resultError = nil;
-
- beforeEach(^{
- resultError = nil;
- hasCalledOperationCompletionHandler = NO;
-
- testConnectionManager = [[TestConnectionManager alloc] init];
- testFileManager = OCMClassMock([SDLFileManager class]);
- });
-
- it(@"should have a priority of 'normal'", ^{
- testOp = [[SDLPreloadChoicesOperation alloc] init];
-
- expect(@(testOp.queuePriority)).to(equal(@(NSOperationQueuePriorityNormal)));
- });
-
- describe(@"running the operation", ^{
- __block SDLWindowCapability *windowCapability = nil;
- beforeEach(^{
- windowCapability = [[SDLWindowCapability alloc] init];
- windowCapability.imageTypeSupported = @[SDLImageTypeStatic, SDLImageTypeDynamic];
- SDLTextField *primaryTextField = [[SDLTextField alloc] init];
- primaryTextField.name = SDLTextFieldNameMenuName;
- windowCapability.textFields = @[primaryTextField];
-
- OCMStub([testFileManager uploadArtworks:[OCMArg any] completionHandler:[OCMArg invokeBlock]]);
- OCMStub([testFileManager fileNeedsUpload:[OCMArg isNotNil]]).andReturn(YES);
- });
-
- context(@"with artworks", ^{
- __block NSOrderedSet<SDLChoiceCell *> *cellsWithArtwork = nil;
- __block NSOrderedSet<SDLChoiceCell *> *cellsWithStaticIcon = nil;
- __block NSString *art1Name = @"Art1Name";
- __block NSString *art2Name = @"Art2Name";
- __block SDLArtwork *cell1Art2 = [[SDLArtwork alloc] initWithData:cellArtData2 name:art1Name fileExtension:@"png" persistent:NO];
-
- beforeEach(^{
- SDLArtwork *cell1Art = [[SDLArtwork alloc] initWithData:cellArtData name:art1Name fileExtension:@"png" persistent:NO];
- SDLChoiceCell *cell1WithArt = [[SDLChoiceCell alloc] initWithText:@"Cell1" artwork:cell1Art voiceCommands:nil];
-
- SDLArtwork *cell2Art = [[SDLArtwork alloc] initWithData:cellArtData name:art2Name fileExtension:@"png" persistent:NO];
- SDLChoiceCell *cell2WithArtAndSecondary = [[SDLChoiceCell alloc] initWithText:@"Cell2" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:cell2Art secondaryArtwork:cell2Art];
-
- SDLArtwork *staticIconArt = [SDLArtwork artworkWithStaticIcon:SDLStaticIconNameDate];
- SDLChoiceCell *cellWithStaticIcon = [[SDLChoiceCell alloc] initWithText:@"Static Icon" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:staticIconArt secondaryArtwork:nil];
-
- cellsWithArtwork = [[NSOrderedSet alloc] initWithArray:@[cell1WithArt, cell2WithArtAndSecondary]];
- cellsWithStaticIcon = [[NSOrderedSet alloc] initWithArray:@[cellWithStaticIcon]];
- });
-
- context(@"if the menuName is not set", ^{
- it(@"should not send any requests", ^{
- SDLTextField *primaryTextField = [[SDLTextField alloc] init];
- primaryTextField.name = SDLTextFieldNameMenuName;
- windowCapability.textFields = @[];
-
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:cellsWithArtwork updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
-
- NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
-
- expect(receivedRequests).to(haveCount(0));
- });
- });
-
- context(@"only main text capabilities", ^{
- it(@"should skip to preloading cells", ^{
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:cellsWithArtwork updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
-
- expect(@(testOp.currentState)).to(equal(SDLPreloadChoicesOperationStatePreloadingChoices));
- });
- });
-
- context(@"only main text and image capabilities", ^{
- beforeEach(^{
- SDLImageField *choiceField = [[SDLImageField alloc] init];
- choiceField.name = SDLImageFieldNameChoiceImage;
- windowCapability.imageFields = @[choiceField];
-
- OCMStub([testFileManager hasUploadedFile:[OCMArg isNotNil]]).andReturn(NO);
-
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:cellsWithArtwork updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
- });
-
- it(@"should upload some artworks", ^{
- OCMVerify([testFileManager uploadArtworks:[OCMArg checkWithBlock:^BOOL(id obj) {
- NSArray<SDLArtwork *> *artworks = (NSArray<SDLArtwork *> *)obj;
- return (artworks.count == 2);
- }] completionHandler:[OCMArg any]]);
- expect(@(testOp.currentState)).to(equal(SDLPreloadChoicesOperationStatePreloadingChoices));
- });
- });
-
- context(@"main text and all image display capabilities", ^{
- beforeEach(^{
- SDLImageField *choiceField = [[SDLImageField alloc] init];
- choiceField.name = SDLImageFieldNameChoiceImage;
- SDLImageField *choiceSecondaryField = [[SDLImageField alloc] init];
- choiceSecondaryField.name = SDLImageFieldNameChoiceSecondaryImage;
-
- windowCapability.imageFields = @[choiceField, choiceSecondaryField];
- });
-
- context(@"when artworks are already on the system", ^{
- beforeEach(^{
- OCMStub([testFileManager hasUploadedFile:[OCMArg isNotNil]]).andReturn(YES);
-
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:cellsWithArtwork updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
- });
-
- it(@"should not upload artworks", ^{
- OCMReject([testFileManager uploadArtworks:[OCMArg checkWithBlock:^BOOL(id obj) {
- NSArray<SDLArtwork *> *artworks = (NSArray<SDLArtwork *> *)obj;
- return (artworks.count == 2);
- }] completionHandler:[OCMArg any]]);
- expect(@(testOp.currentState)).to(equal(SDLPreloadChoicesOperationStatePreloadingChoices));
- });
-
- it(@"should properly overwrite artwork", ^{
- cell1Art2.overwrite = YES;
- SDLChoiceCell *cell1WithArt = [[SDLChoiceCell alloc] initWithText:@"Cell1" artwork:cell1Art2 voiceCommands:nil];
-
- SDLArtwork *cell2Art = [[SDLArtwork alloc] initWithData:cellArtData name:art2Name fileExtension:@"png" persistent:NO];
- SDLChoiceCell *cell2WithArtAndSecondary = [[SDLChoiceCell alloc] initWithText:@"Cell2" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:cell2Art secondaryArtwork:cell2Art];
-
- SDLArtwork *staticIconArt = [SDLArtwork artworkWithStaticIcon:SDLStaticIconNameDate];
- SDLChoiceCell *cellWithStaticIcon = [[SDLChoiceCell alloc] initWithText:@"Static Icon" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:staticIconArt secondaryArtwork:nil];
-
- cellsWithArtwork = [[NSOrderedSet alloc] initWithArray:@[cell1WithArt, cell2WithArtAndSecondary]];
- cellsWithStaticIcon = [[NSOrderedSet alloc] initWithArray:@[cellWithStaticIcon]];
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:cellsWithArtwork updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
-
- OCMExpect([testFileManager uploadArtworks:[OCMArg any] completionHandler:[OCMArg any]]);
- OCMVerify([testFileManager uploadArtworks:[OCMArg any] completionHandler:[OCMArg any]]);
- });
- });
-
- context(@"when artworks are static icons", ^{
- beforeEach(^{
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:cellsWithStaticIcon updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
- });
-
- it(@"should skip uploading artwork", ^{
- OCMReject([testFileManager uploadArtwork:[OCMArg any] completionHandler:[OCMArg any]]);
- });
- });
-
- context(@"when artwork are not already on the system", ^{
- beforeEach(^{
- OCMStub([testFileManager hasUploadedFile:[OCMArg isNotNil]]).andReturn(NO);
-
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:cellsWithArtwork updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
- });
-
- it(@"should upload artworks", ^{
- OCMVerify([testFileManager uploadArtworks:[OCMArg checkWithBlock:^BOOL(id obj) {
- NSArray<SDLArtwork *> *artworks = (NSArray<SDLArtwork *> *)obj;
- return (artworks.count == 3);
- }] completionHandler:[OCMArg any]]);
- expect(@(testOp.currentState)).to(equal(SDLPreloadChoicesOperationStatePreloadingChoices));
- });
- });
- });
- });
-
- context(@"without artworks", ^{
- __block NSOrderedSet<SDLChoiceCell *> *cellsWithoutArtwork = nil;
- beforeEach(^{
- SDLChoiceCell *cellBasic = [[SDLChoiceCell alloc] initWithText:@"Cell1" artwork:nil voiceCommands:nil];
- SDLChoiceCell *cellWithVR = [[SDLChoiceCell alloc] initWithText:@"Cell2" secondaryText:nil tertiaryText:nil voiceCommands:@[@"Cell2"] artwork:nil secondaryArtwork:nil];
- SDLChoiceCell *cellWithAllText = [[SDLChoiceCell alloc] initWithText:@"Cell2" secondaryText:@"Cell2" tertiaryText:@"Cell2" voiceCommands:nil artwork:nil secondaryArtwork:nil];
- cellsWithoutArtwork = [[NSOrderedSet alloc] initWithArray:@[cellBasic, cellWithVR, cellWithAllText]];
- });
-
- it(@"should skip to preloading cells", ^{
- expect(@(testOp.currentState)).to(equal(SDLPreloadChoicesOperationStatePreloadingChoices));
- });
-
- describe(@"assembling choices", ^{
- it(@"should be correct with no text and VR required", ^{
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:cellsWithoutArtwork updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
- NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
-
- expect(receivedRequests).to(haveCount(3));
- expect(receivedRequests.lastObject.choiceSet.firstObject.menuName).toNot(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.secondaryText).to(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.tertiaryText).to(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.vrCommands).toNot(beNil());
- });
-
- it(@"should be correct with only primary text", ^{
- SDLTextField *primaryTextField = [[SDLTextField alloc] init];
- primaryTextField.name = SDLTextFieldNameMenuName;
- windowCapability.textFields = @[primaryTextField];
-
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:cellsWithoutArtwork updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
-
- NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
-
- expect(receivedRequests).to(haveCount(3));
- expect(receivedRequests.lastObject.choiceSet.firstObject.menuName).toNot(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.secondaryText).to(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.tertiaryText).to(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.vrCommands).toNot(beNil());
- });
-
- it(@"should be correct with primary and secondary text", ^{
- SDLTextField *primaryTextField = [[SDLTextField alloc] init];
- primaryTextField.name = SDLTextFieldNameMenuName;
- SDLTextField *secondaryTextField = [[SDLTextField alloc] init];
- secondaryTextField.name = SDLTextFieldNameSecondaryText;
- windowCapability.textFields = @[primaryTextField, secondaryTextField];
-
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:cellsWithoutArtwork updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
-
- NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
-
- expect(receivedRequests).to(haveCount(3));
- expect(receivedRequests.lastObject.choiceSet.firstObject.menuName).toNot(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.secondaryText).toNot(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.tertiaryText).to(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.vrCommands).toNot(beNil());
- });
-
- it(@"should be correct with all text", ^{
- SDLTextField *primaryTextField = [[SDLTextField alloc] init];
- primaryTextField.name = SDLTextFieldNameMenuName;
- SDLTextField *secondaryTextField = [[SDLTextField alloc] init];
- secondaryTextField.name = SDLTextFieldNameSecondaryText;
- SDLTextField *tertiaryTextField = [[SDLTextField alloc] init];
- tertiaryTextField.name = SDLTextFieldNameTertiaryText;
- windowCapability.textFields = @[primaryTextField, secondaryTextField, tertiaryTextField];
-
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:cellsWithoutArtwork updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
-
- NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
-
- expect(receivedRequests).to(haveCount(3));
- expect(receivedRequests.lastObject.choiceSet.firstObject.menuName).toNot(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.secondaryText).toNot(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.tertiaryText).toNot(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.vrCommands).toNot(beNil());
- });
-
- it(@"should be correct with VR optional", ^{
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:YES cellsToPreload:cellsWithoutArtwork updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
-
- NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
-
- expect(receivedRequests).to(haveCount(3));
- expect(receivedRequests.lastObject.choiceSet.firstObject.menuName).toNot(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.secondaryText).to(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.tertiaryText).to(beNil());
- expect(receivedRequests.lastObject.choiceSet.firstObject.vrCommands).to(beNil());
- });
- });
- });
-
- context(@"updating choices", ^{
- __block SDLChoiceCell *testCell1 = nil;
- __block SDLChoiceCell *testCell2 = nil;
- __block NSOrderedSet<SDLChoiceCell *> *testCells = nil;
-
- beforeEach(^{
- testCell1 = [[SDLChoiceCell alloc] initWithText:@"Cell1" artwork:nil voiceCommands:nil];
- testCell2 = [[SDLChoiceCell alloc] initWithText:@"Cell2" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:[SDLArtwork artworkWithStaticIcon:SDLStaticIconNameClock]];
- testCells = [[NSOrderedSet alloc] initWithArray:@[testCell1, testCell2]];
- });
-
- describe(@"if a choice item is removed", ^{
- it(@"should be removed if the removal is attempted while the operation is pending", ^{
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:testCells updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp removeChoicesFromUpload:[NSSet setWithArray:@[testCell1]]];
- [testOp start];
-
- NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
-
- expect(receivedRequests).to(haveCount(1));
- expect(receivedRequests[0].choiceSet[0].menuName).to(equal(testCell2.text));
- });
-
- it(@"should not be removed if the removal is attempted while operation is executing", ^{
- SDLTextField *primaryTextField = [[SDLTextField alloc] init];
- primaryTextField.name = SDLTextFieldNameMenuName;
- windowCapability.textFields = @[primaryTextField];
-
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:testCells updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
- [testOp removeChoicesFromUpload:[NSSet setWithArray:@[testCell1]]];
-
- NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
-
- expect(receivedRequests).to(haveCount(2));
- expect(receivedRequests[0].choiceSet[0].menuName).to(equal(testCell1.text));
- expect(receivedRequests[1].choiceSet[0].menuName).to(equal(testCell2.text));
- });
- });
- });
-
- describe(@"the module's response to choice uploads", ^{
- __block SDLChoiceCell *testCell1 = nil;
- __block SDLChoiceCell *testCell2 = nil;
- __block NSOrderedSet<SDLChoiceCell *> *testCells = nil;
- __block SDLCreateInteractionChoiceSetResponse *testBadResponse = nil;
- __block SDLCreateInteractionChoiceSetResponse *testGoodResponse = nil;
-
- beforeEach(^{
- testCell1 = [[SDLChoiceCell alloc] initWithText:@"Cell1" artwork:nil voiceCommands:nil];
- testCell1.choiceId = 55;
- testCell2 = [[SDLChoiceCell alloc] initWithText:@"Cell2" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:[SDLArtwork artworkWithStaticIcon:SDLStaticIconNameClock]];
- testCell2.choiceId = 66;
- testCells = [[NSOrderedSet alloc] initWithArray:@[testCell1, testCell2]];
-
- testBadResponse = [[SDLCreateInteractionChoiceSetResponse alloc] init];
- testBadResponse.success = @NO;
- testBadResponse.resultCode = SDLResultRejected;
-
- testGoodResponse = [[SDLCreateInteractionChoiceSetResponse alloc] init];
- testGoodResponse.success = @YES;
- testGoodResponse.resultCode = SDLResultSuccess;
- });
-
- context(@"when a bad response comes back", ^{
- it(@"should add the choiceID of the failed choice item to the failedChoiceUploadIDs array", ^{
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:testCells updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
-
- NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
-
- expect(receivedRequests).to(haveCount(2));
- expect(receivedRequests[0].choiceSet[0].menuName).to(equal(testCell1.text));
- expect(receivedRequests[1].choiceSet[0].menuName).to(equal(testCell2.text));
-
- [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:0 error:nil];
- [testConnectionManager respondToRequestWithResponse:testBadResponse requestNumber:1 error:[NSError errorWithDomain:SDLErrorDomainChoiceSetManager code:SDLChoiceSetManagerErrorUploadFailed userInfo:nil]];
-
- expect(testOp.failedChoiceUploadIDs.count).to(equal(1));
- expect(testOp.failedChoiceUploadIDs).to(contain(@(testCell2.choiceId)));
- expect(testOp.failedChoiceUploadIDs).toNot(contain(@(testCell1.choiceId)));
- });
- });
-
- context(@"when only good responses comes back", ^{
- it(@"should leave the failedChoiceUploadIDs array empty", ^{
- testOp = [[SDLPreloadChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:windowCapability isVROptional:NO cellsToPreload:testCells updateCompletionHandler:^(NSArray<NSNumber *> * _Nullable failedChoiceUploadIDs) {}];
- [testOp start];
-
- NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
-
- expect(receivedRequests).to(haveCount(2));
- expect(receivedRequests[0].choiceSet[0].menuName).to(equal(testCell1.text));
- expect(receivedRequests[1].choiceSet[0].menuName).to(equal(testCell2.text));
-
- [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:0 error:nil];
- [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:1 error:nil];
-
- expect(testOp.failedChoiceUploadIDs).to(beEmpty());
- });
- });
- });
- });
-});
-
-QuickSpecEnd
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLPreloadPresentChoicesOperationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLPreloadPresentChoicesOperationSpec.m
new file mode 100644
index 000000000..45e4b7efc
--- /dev/null
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLPreloadPresentChoicesOperationSpec.m
@@ -0,0 +1,1070 @@
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+#import <OCMock/OCMock.h>
+
+#import <SmartDeviceLink/SmartDeviceLink.h>
+#import "SDLError.h"
+#import "SDLPreloadPresentChoicesOperation.h"
+
+#import "SDLGlobals.h"
+#import "TestConnectionManager.h"
+
+@interface SDLPreloadPresentChoicesOperation()
+
+// Dependencies
+@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
+@property (weak, nonatomic) SDLFileManager *fileManager;
+@property (strong, nonatomic) SDLWindowCapability *windowCapability;
+
+// Preload Dependencies
+@property (strong, nonatomic) NSMutableOrderedSet<SDLChoiceCell *> *cellsToUpload;
+@property (strong, nonatomic) NSString *displayName;
+@property (assign, nonatomic, readwrite, getter=isVROptional) BOOL vrOptional;
+@property (copy, nonatomic) SDLUploadChoicesCompletionHandler preloadCompletionHandler;
+
+// Present Dependencies
+@property (strong, nonatomic) SDLChoiceSet *choiceSet;
+@property (strong, nonatomic, nullable) SDLInteractionMode presentationMode;
+@property (strong, nonatomic, nullable) SDLKeyboardProperties *originalKeyboardProperties;
+@property (strong, nonatomic, nullable) SDLKeyboardProperties *customKeyboardProperties;
+@property (weak, nonatomic, nullable) id<SDLKeyboardDelegate> keyboardDelegate;
+@property (assign, nonatomic) UInt16 cancelId;
+
+// Internal operation properties
+@property (strong, nonatomic) NSUUID *operationId;
+@property (copy, nonatomic, nullable) NSError *internalError;
+
+// Mutable state
+@property (strong, nonatomic) NSMutableSet<SDLChoiceCell *> *mutableLoadedCells;
+
+@end
+
+@interface SDLChoiceCell()
+
+@property (assign, nonatomic) UInt16 choiceId;
+@property (assign, nonatomic) NSUInteger uniqueTextId;
+
+@end
+
+QuickSpecBegin(SDLPreloadPresentChoicesOperationSpec)
+
+describe(@"a preload choices operation", ^{
+ __block TestConnectionManager *testConnectionManager = nil;
+ __block SDLFileManager *testFileManager = nil;
+ __block SDLPreloadPresentChoicesOperation *testOp = nil;
+ __block NSString *testDisplayName = @"SDL_GENERIC";
+ __block SDLVersion *choiceSetUniquenessActiveVersion = [[SDLVersion alloc] initWithMajor:7 minor:1 patch:0];
+ __block SDLVersion *choiceSetUniquenessInactiveVersion = [[SDLVersion alloc] initWithMajor:7 minor:0 patch:0];
+
+ __block SDLWindowCapability *enabledWindowCapability = nil;
+ __block SDLWindowCapability *disabledWindowCapability = nil;
+ __block SDLWindowCapability *primaryTextOnlyCapability = nil;
+
+ __block NSSet<SDLChoiceCell *> *emptyLoadedCells = [NSSet set];
+ __block NSArray<SDLChoiceCell *> *cellsWithArtwork = nil;
+ __block NSArray<SDLChoiceCell *> *cellsWithStaticIcon = nil;
+ __block NSArray<SDLChoiceCell *> *cellsWithoutArtwork = nil;
+
+ __block NSData *cellArtData = [@"testart" dataUsingEncoding:NSUTF8StringEncoding];
+ __block NSData *cellArtData2 = [@"testart2" dataUsingEncoding:NSUTF8StringEncoding];
+ __block NSString *art1Name = @"Art1Name";
+ __block NSString *art2Name = @"Art2Name";
+ SDLArtwork *cell1Art = [[SDLArtwork alloc] initWithData:cellArtData name:art1Name fileExtension:@"png" persistent:NO];
+ SDLArtwork *cell1Art2 = [[SDLArtwork alloc] initWithData:cellArtData2 name:art1Name fileExtension:@"png" persistent:NO];
+ SDLArtwork *cell2Art = [[SDLArtwork alloc] initWithData:cellArtData name:art2Name fileExtension:@"png" persistent:NO];
+
+ __block SDLChoiceCell *cellBasic = nil;
+ __block SDLChoiceCell *cellBasicDuplicate = nil;
+ __block SDLChoiceCell *cellWithVR = nil;
+ __block SDLChoiceCell *cellWithAllText = nil;
+
+ __block SDLCreateInteractionChoiceSetResponse *testBadResponse = nil;
+ __block SDLCreateInteractionChoiceSetResponse *testGoodResponse = nil;
+
+ __block NSSet<SDLChoiceCell *> *resultChoices = nil;
+ __block NSError *resultPreloadError = nil;
+
+ __block SDLChoiceSet *testChoiceSet = nil;
+ __block int testCancelID = 98;
+ __block SDLInteractionMode testInteractionMode = SDLInteractionModeBoth;
+ __block SDLKeyboardProperties *testKeyboardProperties = nil;
+ __block id<SDLKeyboardDelegate> testKeyboardDelegate = nil;
+ __block id<SDLChoiceSetDelegate> testChoiceDelegate = nil;
+
+ beforeEach(^{
+ resultPreloadError = nil;
+ resultChoices = nil;
+
+ testConnectionManager = [[TestConnectionManager alloc] init];
+ testFileManager = OCMClassMock([SDLFileManager class]);
+ OCMStub([testFileManager uploadArtworks:[OCMArg any] completionHandler:[OCMArg invokeBlock]]);
+ OCMStub([testFileManager fileNeedsUpload:[OCMArg isNotNil]]).andReturn(YES);
+
+ enabledWindowCapability = [[SDLWindowCapability alloc] init];
+ enabledWindowCapability.textFields = @[
+ [[SDLTextField alloc] initWithName:SDLTextFieldNameMenuName characterSet:SDLCharacterSetUtf8 width:500 rows:1],
+ [[SDLTextField alloc] initWithName:SDLTextFieldNameSecondaryText characterSet:SDLCharacterSetUtf8 width:500 rows:1],
+ [[SDLTextField alloc] initWithName:SDLTextFieldNameTertiaryText characterSet:SDLCharacterSetUtf8 width:500 rows:1]
+ ];
+ enabledWindowCapability.imageFields = @[
+ [[SDLImageField alloc] initWithName:SDLImageFieldNameChoiceImage imageTypeSupported:@[SDLFileTypePNG] imageResolution:nil],
+ [[SDLImageField alloc] initWithName:SDLImageFieldNameChoiceSecondaryImage imageTypeSupported:@[SDLFileTypePNG] imageResolution:nil]
+ ];
+ disabledWindowCapability = [[SDLWindowCapability alloc] init];
+ disabledWindowCapability.textFields = @[];
+ primaryTextOnlyCapability = [[SDLWindowCapability alloc] init];
+ primaryTextOnlyCapability.textFields = @[
+ [[SDLTextField alloc] initWithName:SDLTextFieldNameMenuName characterSet:SDLCharacterSetUtf8 width:500 rows:1],
+ ];
+
+ SDLChoiceCell *cell1WithArt = [[SDLChoiceCell alloc] initWithText:@"Cell1" artwork:cell1Art voiceCommands:nil];
+ cell1WithArt.choiceId = 1;
+ SDLChoiceCell *cell2WithArtAndSecondary = [[SDLChoiceCell alloc] initWithText:@"Cell2" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:cell2Art secondaryArtwork:cell2Art];
+ cell2WithArtAndSecondary.choiceId = 2;
+
+ SDLArtwork *staticIconArt = [SDLArtwork artworkWithStaticIcon:SDLStaticIconNameDate];
+ SDLChoiceCell *cellWithStaticIcon = [[SDLChoiceCell alloc] initWithText:@"Static Icon" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:staticIconArt secondaryArtwork:nil];
+ cellWithStaticIcon.choiceId = 3;
+
+ cellsWithArtwork = @[cell1WithArt, cell2WithArtAndSecondary];
+ cellsWithStaticIcon = @[cellWithStaticIcon];
+
+ cellBasic = [[SDLChoiceCell alloc] initWithText:@"Cell1" artwork:nil voiceCommands:nil];
+ cellBasic.choiceId = 4;
+ cellBasicDuplicate = [[SDLChoiceCell alloc] initWithText:@"Cell1" artwork:nil voiceCommands:nil];
+ cellBasicDuplicate.choiceId = 5;
+ cellWithVR = [[SDLChoiceCell alloc] initWithText:@"Cell2" secondaryText:nil tertiaryText:nil voiceCommands:@[@"Cell2"] artwork:nil secondaryArtwork:nil];
+ cellWithVR.choiceId = 6;
+ cellWithAllText = [[SDLChoiceCell alloc] initWithText:@"Cell2" secondaryText:@"Cell2" tertiaryText:@"Cell2" voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ cellWithAllText.choiceId = 7;
+ cellsWithoutArtwork = @[cellBasic, cellWithVR, cellWithAllText];
+
+ testBadResponse = [[SDLCreateInteractionChoiceSetResponse alloc] init];
+ testBadResponse.success = @NO;
+ testBadResponse.resultCode = SDLResultRejected;
+
+ testGoodResponse = [[SDLCreateInteractionChoiceSetResponse alloc] init];
+ testGoodResponse.success = @YES;
+ testGoodResponse.resultCode = SDLResultSuccess;
+
+ testChoiceDelegate = OCMProtocolMock(@protocol(SDLChoiceSetDelegate));
+ testKeyboardDelegate = OCMProtocolMock(@protocol(SDLKeyboardDelegate));
+ OCMStub([testKeyboardDelegate customKeyboardConfiguration]).andReturn(nil);
+ testKeyboardProperties = [[SDLKeyboardProperties alloc] initWithLanguage:SDLLanguageArSa keyboardLayout:SDLKeyboardLayoutAZERTY keypressMode:SDLKeypressModeResendCurrentEntry limitedCharacterList:nil autoCompleteList:nil maskInputCharacters:nil customKeys:nil];
+ testChoiceSet = [[SDLChoiceSet alloc] initWithTitle:@"Choice Set" delegate:testChoiceDelegate layout:SDLChoiceSetLayoutTiles timeout:8.0 initialPromptString:@"Initial Prompt" timeoutPromptString:@"Timeout Prompt" helpPromptString:@"Help Prompt" vrHelpList:nil choices:cellsWithoutArtwork];
+ });
+
+ it(@"should have a priority of 'normal'", ^{
+ testOp = [[SDLPreloadPresentChoicesOperation alloc] init];
+
+ expect(@(testOp.queuePriority)).to(equal(@(NSOperationQueuePriorityNormal)));
+ });
+
+ context(@"running a preload only operation", ^{
+ describe(@"updating cells for uniqueness", ^{
+ beforeEach(^{
+ testOp = [[SDLPreloadPresentChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:enabledWindowCapability isVROptional:YES cellsToPreload:@[cellWithVR] loadedCells:[NSSet setWithArray:@[cellWithAllText]] preloadCompletionHandler:^(NSSet<SDLChoiceCell *> * _Nonnull updatedLoadedCells, NSError * _Nullable error) {}];
+ });
+
+ context(@"when some choices are already uploaded with duplicate titles version >= 7.1.0", ^{
+ beforeEach(^{
+ [SDLGlobals sharedGlobals].rpcVersion = choiceSetUniquenessActiveVersion;
+ });
+
+ context(@"if there are duplicate cells once you strip unused cell properties", ^{
+ beforeEach(^{
+ SDLChoiceCell *loadedCell1 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Loaded 1" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ SDLChoiceCell *loadedCell2 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Loaded 2" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ loadedCell2.uniqueTextId = 3;
+ SDLChoiceCell *loadedCell3 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Loaded 3" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ loadedCell3.uniqueTextId = 5;
+
+ SDLChoiceCell *cellToUpload1 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Unique 1" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ SDLChoiceCell *cellToUpload2 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Unique 2" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ SDLChoiceCell *cellToUpload3 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Unique 3" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ SDLChoiceCell *cellToUpload4 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Unique 4" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+
+ testOp.windowCapability = primaryTextOnlyCapability;
+ testOp.loadedCells = [NSSet setWithArray:@[loadedCell1, loadedCell2, loadedCell3]];
+ testOp.cellsToUpload = [NSMutableOrderedSet orderedSetWithArray:@[cellToUpload1, cellToUpload2, cellToUpload3, cellToUpload4]];
+ [testOp start];
+ });
+
+ it(@"should properly assign unique text", ^{
+ expect(testOp.cellsToUpload[0].uniqueText).to(equal(@"Cell 2 (2)"));
+ expect(testOp.cellsToUpload[1].uniqueText).to(equal(@"Cell 2 (4)"));
+ expect(testOp.cellsToUpload[2].uniqueText).to(equal(@"Cell 2 (6)"));
+ expect(testOp.cellsToUpload[3].uniqueText).to(equal(@"Cell 2 (7)"));
+ expect(testOp.cellsToUpload[0].secondaryText).toNot(beNil());
+ });
+ });
+
+ context(@"if all cell properties are used", ^{
+ beforeEach(^{
+ testOp.windowCapability = enabledWindowCapability;
+ [testOp start];
+ });
+
+ it(@"should not update the choiceCells' unique title", ^{
+ expect(testOp.cellsToUpload[0].uniqueText).to(equal("Cell2"));
+ expect(testOp.cellsToUpload.count).to(equal(1));
+ });
+ });
+ });
+
+ context(@"when some choices are already uploaded with duplicate titles version <= 7.1.0", ^{
+ beforeEach(^{
+ [SDLGlobals sharedGlobals].rpcVersion = choiceSetUniquenessInactiveVersion;
+ });
+
+ context(@"if all cell properties are used", ^{
+ beforeEach(^{
+ testOp.windowCapability = enabledWindowCapability;
+ [testOp start];
+ });
+
+ it(@"should update the choiceCells' unique title", ^{
+ expect(testOp.cellsToUpload[0].uniqueText).to(equal("Cell2 (2)"));
+ expect(testOp.cellsToUpload.count).to(equal(1));
+ });
+ });
+ });
+ });
+
+ context(@"with artworks", ^{
+ context(@"only primary text allowed", ^{
+ it(@"should skip loading artworks to preloading cells", ^{
+ testOp = [[SDLPreloadPresentChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:primaryTextOnlyCapability isVROptional:YES cellsToPreload:cellsWithArtwork loadedCells:emptyLoadedCells preloadCompletionHandler:^(NSSet<SDLChoiceCell *> * _Nonnull updatedLoadedCells, NSError * _Nullable error) {
+ resultPreloadError = error;
+ resultChoices = updatedLoadedCells;
+ }];
+ [testOp start];
+
+ for (SDLRPCRequest *request in testConnectionManager.receivedRequests) {
+ expect(request).toNot(beAnInstanceOf(SDLPutFile.class));
+ }
+ expect(testConnectionManager.receivedRequests).to(haveCount(2));
+ });
+ });
+
+ context(@"all text and image display capabilities", ^{
+ beforeEach(^{
+ testOp = [[SDLPreloadPresentChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:enabledWindowCapability isVROptional:YES cellsToPreload:cellsWithArtwork loadedCells:emptyLoadedCells preloadCompletionHandler:^(NSSet<SDLChoiceCell *> * _Nonnull updatedLoadedCells, NSError * _Nullable error) {
+ resultPreloadError = error;
+ resultChoices = updatedLoadedCells;
+ }];
+ });
+
+ context(@"when artworks are already on the system", ^{
+ beforeEach(^{
+ OCMStub([testFileManager hasUploadedFile:[OCMArg isNotNil]]).andReturn(YES);
+ });
+
+ it(@"should not upload artworks", ^{
+ OCMReject([testFileManager uploadArtworks:[OCMArg checkWithBlock:^BOOL(id obj) {
+ NSArray<SDLArtwork *> *artworks = (NSArray<SDLArtwork *> *)obj;
+ return (artworks.count == 2);
+ }] completionHandler:[OCMArg any]]);
+
+ [testOp start];
+
+ OCMVerifyAll(testFileManager);
+ });
+
+ it(@"should properly overwrite artwork", ^{
+ cell1Art2.overwrite = YES;
+ SDLChoiceCell *cellOverwriteArt = [[SDLChoiceCell alloc] initWithText:@"Cell1" artwork:cell1Art2 voiceCommands:nil];
+
+ testOp.cellsToUpload = [NSMutableOrderedSet orderedSetWithArray:@[cellOverwriteArt]];
+ [testOp start];
+
+ OCMVerify([testFileManager uploadArtworks:[OCMArg isNotNil] completionHandler:[OCMArg any]]);
+ });
+ });
+
+ context(@"when artworks are static icons", ^{
+ beforeEach(^{
+ testOp.cellsToUpload = [NSMutableOrderedSet orderedSetWithArray:cellsWithStaticIcon];
+ [testOp start];
+ });
+
+ it(@"should skip uploading artwork", ^{
+ OCMReject([testFileManager uploadArtwork:[OCMArg any] completionHandler:[OCMArg any]]);
+ });
+ });
+
+ fcontext(@"when artworks are not already on the system", ^{
+ beforeEach(^{
+ OCMStub([testFileManager hasUploadedFile:[OCMArg isNotNil]]).andReturn(NO);
+ });
+
+ context(@"when there's more than one of the same artwork", ^{
+ beforeEach(^{
+ testOp.cellsToUpload = [NSMutableOrderedSet orderedSetWithArray:@[
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" artwork:cell1Art voiceCommands:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 2" artwork:cell1Art voiceCommands:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 3" artwork:cell1Art voiceCommands:nil],
+ ]];
+ testOp.loadedCells = [NSSet set];
+ });
+
+ it(@"should only attempt to upload one of each art", ^{
+ [testOp start];
+ OCMVerify([testFileManager uploadArtworks:[OCMArg checkWithBlock:^BOOL(id obj) {
+ NSArray<SDLArtwork *> *artworks = (NSArray<SDLArtwork *> *)obj;
+ return (artworks.count == 1);
+ }] completionHandler:[OCMArg any]]);
+ });
+ });
+
+ context(@"when uploading unique art", ^{
+ beforeEach(^{
+ testOp.cellsToUpload = [NSMutableOrderedSet orderedSetWithArray:cellsWithArtwork];
+ testOp.loadedCells = [NSSet set];
+ });
+
+ it(@"should upload artworks", ^{
+ [testOp start];
+ OCMVerify([testFileManager uploadArtworks:[OCMArg checkWithBlock:^BOOL(id obj) {
+ NSArray<SDLArtwork *> *artworks = (NSArray<SDLArtwork *> *)obj;
+ return (artworks.count == 2);
+ }] completionHandler:[OCMArg any]]);
+ });
+ });
+ });
+ });
+ });
+
+ context(@"without artworks", ^{
+ describe(@"only main text capabilities", ^{
+ it(@"should skip loading artworks to preloading cells", ^{
+ testOp = [[SDLPreloadPresentChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:primaryTextOnlyCapability isVROptional:YES cellsToPreload:cellsWithArtwork loadedCells:emptyLoadedCells preloadCompletionHandler:^(NSSet<SDLChoiceCell *> * _Nonnull updatedLoadedCells, NSError * _Nullable error) {
+ resultPreloadError = error;
+ resultChoices = updatedLoadedCells;
+ }];
+ [testOp start];
+
+ for (SDLRPCRequest *request in testConnectionManager.receivedRequests) {
+ expect(request).toNot(beAnInstanceOf(SDLPutFile.class));
+ }
+ expect(testConnectionManager.receivedRequests).to(haveCount(2));
+ });
+ });
+
+ describe(@"assembling choices", ^{
+ beforeEach(^{
+ testOp = [[SDLPreloadPresentChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:enabledWindowCapability isVROptional:YES cellsToPreload:cellsWithoutArtwork loadedCells:emptyLoadedCells preloadCompletionHandler:^(NSSet<SDLChoiceCell *> * _Nonnull updatedLoadedCells, NSError * _Nullable error) {
+ resultChoices = updatedLoadedCells;
+ resultPreloadError = error;
+ }];
+ });
+
+ it(@"should skip preloading the choices if all choice items have already been uploaded", ^{
+ testOp.loadedCells = [NSSet setWithArray:cellsWithoutArtwork];
+ [testOp start];
+
+ expect(testConnectionManager.receivedRequests).to(haveCount(0));
+ });
+
+ it(@"should not send any requests if all items are disabled", ^{
+ testOp.windowCapability = disabledWindowCapability;
+ [testOp start];
+
+ expect(testConnectionManager.receivedRequests).to(haveCount(0));
+ });
+
+ it(@"should be correct with only primary text", ^{
+ testOp.windowCapability = primaryTextOnlyCapability;
+ [testOp start];
+
+ NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
+
+ expect(receivedRequests).to(haveCount(3));
+
+ SDLChoice *representativeItem = receivedRequests.lastObject.choiceSet.firstObject;
+ expect(representativeItem.menuName).toNot(beNil());
+ expect(representativeItem.secondaryText).to(beNil());
+ expect(representativeItem.tertiaryText).to(beNil());
+ });
+
+ it(@"should be correct with all text", ^{
+ SDLWindowCapability *allTextCapability = [enabledWindowCapability copy];
+ allTextCapability.imageFields = @[];
+ testOp.windowCapability = allTextCapability;
+ [testOp start];
+
+ NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
+
+ expect(receivedRequests).to(haveCount(3));
+
+ SDLChoice *representativeItem = receivedRequests.lastObject.choiceSet.firstObject;
+ expect(representativeItem.menuName).toNot(beNil());
+ expect(representativeItem.secondaryText).toNot(beNil());
+ expect(representativeItem.tertiaryText).toNot(beNil());
+ });
+
+ it(@"should be correct with VR required", ^{
+ testOp.vrOptional = NO;
+ [testOp start];
+
+ NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
+
+ expect(receivedRequests).to(haveCount(3));
+
+ // The last item has no VR
+ SDLChoice *representativeItem = receivedRequests.lastObject.choiceSet.firstObject;
+ expect(representativeItem.vrCommands).toNot(beNil());
+ });
+
+ it(@"should be correct with VR Optional", ^{
+ testOp.vrOptional = YES;
+ [testOp start];
+
+ NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
+
+ expect(receivedRequests).to(haveCount(3));
+
+ // The middle item is the one with VR
+ SDLChoice *representativeItem = receivedRequests.lastObject.choiceSet.firstObject;
+ expect(representativeItem.vrCommands).to(beNil());
+ });
+ });
+ });
+
+ describe(@"the module's response to choice uploads", ^{
+ context(@"when a bad response comes back", ^{
+ beforeEach(^{
+ testOp = [[SDLPreloadPresentChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:primaryTextOnlyCapability isVROptional:YES cellsToPreload:cellsWithoutArtwork loadedCells:emptyLoadedCells preloadCompletionHandler:^(NSSet<SDLChoiceCell *> * _Nonnull updatedLoadedCells, NSError * _Nullable error) {
+ resultChoices = updatedLoadedCells;
+ resultPreloadError = error;
+ }];
+ });
+
+ it(@"should not add the item to the list of loaded cells", ^{
+ [testOp start];
+
+ NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
+
+ expect(receivedRequests).to(haveCount(3));
+ expect(receivedRequests[0].choiceSet[0].menuName).to(equal(cellsWithoutArtwork[0].uniqueText));
+ expect(receivedRequests[1].choiceSet[0].menuName).to(equal(cellsWithoutArtwork[1].uniqueText));
+ expect(receivedRequests[2].choiceSet[0].menuName).to(equal(cellsWithoutArtwork[2].uniqueText));
+
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:0 error:nil];
+ [testConnectionManager respondToRequestWithResponse:testBadResponse requestNumber:1 error:[NSError errorWithDomain:SDLErrorDomainChoiceSetManager code:SDLChoiceSetManagerErrorUploadFailed userInfo:nil]];
+ [testConnectionManager respondToLastMultipleRequestsWithSuccess:NO];
+
+ expect(testOp.loadedCells).to(haveCount(1));
+ expect(testOp.loadedCells).to(contain(cellsWithoutArtwork[0]));
+ expect(testOp.loadedCells).toNot(contain(cellsWithoutArtwork[1]));
+ expect(testOp.error).toNot(beNil());
+ expect(resultChoices).toNot(beNil());
+ expect(resultPreloadError).toNot(beNil());
+ });
+ });
+
+ context(@"when only good responses comes back", ^{
+ beforeEach(^{
+ testOp = [[SDLPreloadPresentChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager displayName:testDisplayName windowCapability:primaryTextOnlyCapability isVROptional:YES cellsToPreload:cellsWithoutArtwork loadedCells:emptyLoadedCells preloadCompletionHandler:^(NSSet<SDLChoiceCell *> * _Nonnull updatedLoadedCells, NSError * _Nullable error) {
+ resultChoices = updatedLoadedCells;
+ resultPreloadError = error;
+ }];
+ });
+
+ it(@"should add all the items to the list of loaded cells", ^{
+ [testOp start];
+
+ NSArray<SDLCreateInteractionChoiceSet *> *receivedRequests = (NSArray<SDLCreateInteractionChoiceSet *> *)testConnectionManager.receivedRequests;
+
+ expect(receivedRequests).to(haveCount(3));
+ expect(receivedRequests[0].choiceSet[0].menuName).to(equal(cellsWithoutArtwork[0].uniqueText));
+ expect(receivedRequests[1].choiceSet[0].menuName).to(equal(cellsWithoutArtwork[1].uniqueText));
+ expect(receivedRequests[2].choiceSet[0].menuName).to(equal(cellsWithoutArtwork[2].uniqueText));
+
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:0 error:nil];
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:1 error:nil];
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:2 error:nil];
+ [testConnectionManager respondToLastMultipleRequestsWithSuccess:YES];
+
+ expect(testOp.loadedCells).to(haveCount(3));
+ expect(testOp.loadedCells).to(contain(cellsWithoutArtwork[0]));
+ expect(testOp.loadedCells).to(contain(cellsWithoutArtwork[1]));
+ expect(testOp.loadedCells).to(contain(cellsWithoutArtwork[2]));
+ expect(resultPreloadError).to(beNil());
+ expect(resultChoices).to(haveCount(3));
+ });
+ });
+ });
+ });
+
+ context(@"running a preload and present operation", ^{
+ beforeEach(^{
+ testOp = [[SDLPreloadPresentChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager choiceSet:testChoiceSet mode:testInteractionMode keyboardProperties:testKeyboardProperties keyboardDelegate:testKeyboardDelegate cancelID:testCancelID displayName:testDisplayName windowCapability:enabledWindowCapability isVROptional:YES loadedCells:emptyLoadedCells preloadCompletionHandler:^(NSSet<SDLChoiceCell *> * _Nonnull updatedLoadedCells, NSError * _Nullable error) {
+ resultChoices = updatedLoadedCells;
+ resultPreloadError = error;
+ }];
+ });
+
+ describe(@"updating cells for uniqueness", ^{
+ beforeEach(^{
+ testOp = [[SDLPreloadPresentChoicesOperation alloc] initWithConnectionManager:testConnectionManager fileManager:testFileManager choiceSet:[[SDLChoiceSet alloc] initWithTitle:@"Test Choice Set" delegate:testChoiceDelegate choices:@[cellWithVR]] mode:testInteractionMode keyboardProperties:testKeyboardProperties keyboardDelegate:testKeyboardDelegate cancelID:testCancelID displayName:testDisplayName windowCapability:enabledWindowCapability isVROptional:YES loadedCells:[NSSet setWithArray:@[cellWithAllText]] preloadCompletionHandler:^(NSSet<SDLChoiceCell *> * _Nonnull updatedLoadedCells, NSError * _Nullable error) {
+ resultChoices = updatedLoadedCells;
+ resultPreloadError = error;
+ }];
+ });
+
+ context(@"when some choices are already uploaded with duplicate titles version >= 7.1.0", ^{
+ beforeEach(^{
+ [SDLGlobals sharedGlobals].rpcVersion = choiceSetUniquenessActiveVersion;
+ });
+
+ context(@"if there are duplicate cells once you strip unused cell properties", ^{
+ beforeEach(^{
+ SDLChoiceCell *loadedCell1 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Loaded 1" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ SDLChoiceCell *loadedCell2 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Loaded 2" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ loadedCell2.uniqueTextId = 3;
+ SDLChoiceCell *loadedCell3 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Loaded 3" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ loadedCell3.uniqueTextId = 5;
+
+ SDLChoiceCell *cellToUpload1 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Unique 1" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ SDLChoiceCell *cellToUpload2 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Unique 2" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ SDLChoiceCell *cellToUpload3 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Unique 3" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+ SDLChoiceCell *cellToUpload4 = [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Unique 4" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil];
+
+ testOp.windowCapability = primaryTextOnlyCapability;
+ testOp.loadedCells = [NSSet setWithArray:@[loadedCell1, loadedCell2, loadedCell3]];
+ testOp.choiceSet.choices = @[cellToUpload1, cellToUpload2, cellToUpload3, cellToUpload4];
+ testOp.cellsToUpload = [[NSMutableOrderedSet alloc] initWithArray:@[cellToUpload1, cellToUpload2, cellToUpload3, cellToUpload4]];
+ [testOp start];
+ });
+
+ it(@"should properly assign unique text", ^{
+ expect(testOp.cellsToUpload[0].uniqueText).to(equal(@"Cell 2 (2)"));
+ expect(testOp.cellsToUpload[1].uniqueText).to(equal(@"Cell 2 (4)"));
+ expect(testOp.cellsToUpload[2].uniqueText).to(equal(@"Cell 2 (6)"));
+ expect(testOp.cellsToUpload[3].uniqueText).to(equal(@"Cell 2 (7)"));
+ expect(testOp.cellsToUpload[0].secondaryText).toNot(beNil());
+ expect(testOp.choiceSet.choices[0].uniqueText).to(equal(@"Cell 2 (2)"));
+ });
+ });
+
+ context(@"if all cell properties are used", ^{
+ beforeEach(^{
+ testOp.windowCapability = enabledWindowCapability;
+ [testOp start];
+ });
+
+ it(@"should not update the choiceCells' unique title", ^{
+ expect(testOp.cellsToUpload[0].uniqueText).to(equal(@"Cell2"));
+ expect(testOp.cellsToUpload.count).to(equal(1));
+ expect(testOp.choiceSet.choices[0].uniqueText).to(equal(@"Cell2"));
+ });
+ });
+ });
+
+ context(@"when some choices are already uploaded with duplicate titles version <= 7.1.0", ^{
+ beforeEach(^{
+ [SDLGlobals sharedGlobals].rpcVersion = choiceSetUniquenessInactiveVersion;
+ });
+
+ context(@"if all cell properties are used", ^{
+ beforeEach(^{
+ testOp.windowCapability = enabledWindowCapability;
+ [testOp start];
+ });
+
+ it(@"should update the choiceCells' unique title", ^{
+ expect(testOp.cellsToUpload[0].uniqueText).to(equal("Cell2 (2)"));
+ expect(testOp.cellsToUpload.count).to(equal(1));
+ expect(testOp.choiceSet.choices[0].uniqueText).to(equal(@"Cell2 (2)"));
+ });
+ });
+ });
+ });
+
+ describe(@"running a non-searchable choice set operation", ^{
+ beforeEach(^{
+ testOp.keyboardDelegate = nil;
+ [testOp start];
+
+ // Move us past the preload
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:0 error:nil];
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:1 error:nil];
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:2 error:nil];
+ [testConnectionManager respondToLastMultipleRequestsWithSuccess:YES];
+ });
+
+ it(@"should not update global keyboard properties", ^{
+ for (SDLRPCRequest *req in testConnectionManager.receivedRequests) {
+ expect(req).toNot(beAnInstanceOf([SDLSetGlobalProperties class]));
+ }
+ });
+
+ it(@"should send the perform interaction", ^{
+ SDLPerformInteraction *request = testConnectionManager.receivedRequests.lastObject;
+ expect(request).to(beAnInstanceOf([SDLPerformInteraction class]));
+
+ expect(request.initialText).to(equal(testChoiceSet.title));
+ expect(request.initialPrompt).to(equal(testChoiceSet.initialPrompt));
+ expect(request.interactionMode).to(equal(testInteractionMode));
+ expect(request.interactionLayout).to(equal(SDLLayoutModeIconOnly));
+ expect(request.timeoutPrompt).to(equal(testChoiceSet.timeoutPrompt));
+ expect(request.helpPrompt).to(equal(testChoiceSet.helpPrompt));
+ expect(request.timeout).to(equal(testChoiceSet.timeout * 1000));
+ expect(request.vrHelp).to(beNil());
+ expect(request.interactionChoiceSetIDList).to(equal(@[@(cellsWithoutArtwork[0].choiceId), @(cellsWithoutArtwork[1].choiceId), @(cellsWithoutArtwork[2].choiceId)]));
+ expect(request.cancelID).to(equal(testCancelID));
+ });
+
+ describe(@"after a perform interaction response", ^{
+ __block UInt16 responseChoiceId = UINT16_MAX;
+ __block SDLTriggerSource responseTriggerSource = SDLTriggerSourceMenu;
+
+ beforeEach(^{
+ SDLPerformInteractionResponse *response = [[SDLPerformInteractionResponse alloc] init];
+ response.success = @YES;
+ response.choiceID = @(responseChoiceId);
+ response.triggerSource = responseTriggerSource;
+
+ [testConnectionManager respondToLastRequestWithResponse:response];
+ });
+
+ it(@"should not reset the keyboard properties and should be finished", ^{
+ expect(testConnectionManager.receivedRequests.lastObject).toNot(beAnInstanceOf([SDLSetGlobalProperties class]));
+ expect(testOp.isFinished).to(beTrue());
+ });
+ });
+ });
+
+ describe(@"running a searchable choice set operation", ^{
+ beforeEach(^{
+ [testOp start];
+
+ // Move us past the preload
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:0 error:nil];
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:1 error:nil];
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:2 error:nil];
+ [testConnectionManager respondToLastMultipleRequestsWithSuccess:YES];
+ });
+
+ it(@"should ask for custom properties", ^{
+ OCMVerify([testKeyboardDelegate customKeyboardConfiguration]);
+
+ expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLSetGlobalProperties class]));
+ });
+
+ describe(@"presenting the keyboard", ^{
+ beforeEach(^{
+ SDLSetGlobalPropertiesResponse *response = [[SDLSetGlobalPropertiesResponse alloc] init];
+ response.success = @YES;
+ [testConnectionManager respondToLastRequestWithResponse:response];
+ });
+
+ it(@"should send the perform interaction", ^{
+ expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLPerformInteraction class]));
+ SDLPerformInteraction *request = testConnectionManager.receivedRequests.lastObject;
+ expect(request.initialText).to(equal(testChoiceSet.title));
+ expect(request.initialPrompt).to(equal(testChoiceSet.initialPrompt));
+ expect(request.interactionMode).to(equal(testInteractionMode));
+ expect(request.interactionLayout).to(equal(SDLLayoutModeIconWithSearch));
+ expect(request.timeoutPrompt).to(equal(testChoiceSet.timeoutPrompt));
+ expect(request.helpPrompt).to(equal(testChoiceSet.helpPrompt));
+ expect(request.timeout).to(equal(testChoiceSet.timeout * 1000));
+ expect(request.vrHelp).to(beNil());
+ expect(request.interactionChoiceSetIDList).to(equal(@[@(testChoiceSet.choices[0].choiceId), @(testChoiceSet.choices[1].choiceId), @(testChoiceSet.choices[2].choiceId)]));
+ expect(request.cancelID).to(equal(testCancelID));
+ });
+
+ it(@"should respond to submitted notifications", ^{
+ NSString *inputData = @"Test";
+ SDLRPCNotificationNotification *notification = nil;
+
+ // Submit notification
+ SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
+ input.event = SDLKeyboardEventSubmitted;
+ input.data = inputData;
+ notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
+
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+
+ OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventSubmitted];
+ }] text:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(NSString *)obj isEqualToString:inputData];
+ }]]);
+
+ OCMVerify([testKeyboardDelegate userDidSubmitInput:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(NSString *)obj isEqualToString:inputData];
+ }] withEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventSubmitted];
+ }]]);
+ });
+
+ it(@"should respond to voice request notifications", ^{
+ SDLRPCNotificationNotification *notification = nil;
+
+ // Submit notification
+ SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
+ input.event = SDLKeyboardEventVoice;
+ notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
+
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+
+ OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventVoice];
+ }] text:[OCMArg isNil]]);
+
+ OCMVerify([testKeyboardDelegate userDidSubmitInput:[OCMArg isNil] withEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventVoice];
+ }]]);
+ });
+
+ it(@"should respond to abort notifications", ^{
+ SDLRPCNotificationNotification *notification = nil;
+
+ // Submit notification
+ SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
+ input.event = SDLKeyboardEventAborted;
+ notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
+
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+
+ OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventAborted];
+ }] text:[OCMArg isNil]]);
+
+ OCMVerify([testKeyboardDelegate keyboardDidAbortWithReason:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventAborted];
+ }]]);
+ });
+
+ it(@"should respond to enabled keyboard event", ^{
+ SDLRPCNotificationNotification *notification = nil;
+
+ // Submit notification
+ SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
+ input.event = SDLKeyboardEventInputKeyMaskEnabled;
+ notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
+
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+
+ OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventInputKeyMaskEnabled];
+ }] text:[OCMArg isNil]]);
+
+ OCMVerify([testKeyboardDelegate keyboardDidUpdateInputMask:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventInputKeyMaskEnabled];
+ }]]);
+ });
+
+ it(@"should respond to cancellation notifications", ^{
+ SDLRPCNotificationNotification *notification = nil;
+
+ // Submit notification
+ SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
+ input.event = SDLKeyboardEventCancelled;
+ notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
+
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+
+ OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventCancelled];
+ }] text:[OCMArg isNil]]);
+
+ OCMVerify([testKeyboardDelegate keyboardDidAbortWithReason:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventCancelled];
+ }]]);
+ });
+
+ it(@"should respond to text input notification with autocomplete", ^{
+ NSString *inputData = @"Test";
+ SDLRPCNotificationNotification *notification = nil;
+
+ OCMStub([testKeyboardDelegate updateAutocompleteWithInput:[OCMArg any] autoCompleteResultsHandler:([OCMArg invokeBlockWithArgs:@[inputData], nil])]);
+
+ // Submit notification
+ SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
+ input.event = SDLKeyboardEventKeypress;
+ input.data = inputData;
+ notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
+
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+
+ OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventKeypress];
+ }] text:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(NSString *)obj isEqualToString:inputData];
+ }]]);
+
+ OCMVerify([testKeyboardDelegate updateAutocompleteWithInput:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(NSString *)obj isEqualToString:inputData];
+ }] autoCompleteResultsHandler:[OCMArg any]]);
+
+ expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLSetGlobalProperties class]));
+
+ SDLSetGlobalProperties *setProperties = testConnectionManager.receivedRequests.lastObject;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ expect(setProperties.keyboardProperties.autoCompleteText).to(equal(inputData));
+#pragma clang diagnostic pop
+ });
+
+ it(@"should respond to text input notification with character set", ^{
+ NSString *inputData = @"Test";
+ SDLRPCNotificationNotification *notification = nil;
+
+ OCMStub([testKeyboardDelegate updateCharacterSetWithInput:[OCMArg any] completionHandler:([OCMArg invokeBlockWithArgs:@[inputData], nil])]);
+
+ // Submit notification
+ SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
+ input.event = SDLKeyboardEventKeypress;
+ input.data = inputData;
+ notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
+
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+
+ OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventKeypress];
+ }] text:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(NSString *)obj isEqualToString:inputData];
+ }]]);
+
+ OCMVerify([testKeyboardDelegate updateCharacterSetWithInput:[OCMArg checkWithBlock:^BOOL(id obj) {
+ return [(NSString *)obj isEqualToString:inputData];
+ }] completionHandler:[OCMArg any]]);
+
+ expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLSetGlobalProperties class]));
+
+ SDLSetGlobalProperties *setProperties = testConnectionManager.receivedRequests.lastObject;
+ expect(setProperties.keyboardProperties.limitedCharacterList).to(equal(@[inputData]));
+ });
+
+ describe(@"after a perform interaction response", ^{
+ beforeEach(^{
+ SDLPerformInteractionResponse *response = [[SDLPerformInteractionResponse alloc] init];
+ response.success = @YES;
+ response.choiceID = @65535;
+ response.triggerSource = SDLTriggerSourceVoiceRecognition;
+
+ [testConnectionManager respondToLastRequestWithResponse:response];
+ });
+
+ it(@"should reset the keyboard properties", ^{
+ expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLSetGlobalProperties class]));
+ });
+
+ describe(@"after the reset response", ^{
+ __block SDLSetGlobalPropertiesResponse *response = [[SDLSetGlobalPropertiesResponse alloc] init];
+ beforeEach(^{
+ response.success = @YES;
+ });
+
+ it(@"should be finished", ^{
+ OCMExpect([testChoiceDelegate choiceSet:[OCMArg isEqual:testChoiceSet] didSelectChoice:[OCMArg isNotNil] withSource:[OCMArg isEqual:SDLTriggerSourceVoiceRecognition] atRowIndex:0]);
+ OCMReject([testChoiceDelegate choiceSet:[OCMArg any] didReceiveError:[OCMArg any]]);
+
+ [testConnectionManager respondToLastRequestWithResponse:response];
+
+ expect(testOp.isFinished).to(beTrue());
+ });
+ });
+ });
+ });
+ });
+
+ describe(@"canceling the choice set", ^{
+ context(@"if the head unit supports the `CancelInteraction` RPC", ^{
+ beforeEach(^{
+ [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithMajor:6 minor:0 patch:0];
+ });
+
+ context(@"if the operation is executing", ^{
+ beforeEach(^{
+ [testOp start];
+ });
+
+ context(@"before the present is sent", ^{
+ it(@"should cancel without a CancelInteraction", ^{
+ expect(testOp.isExecuting).to(beTrue());
+ expect(testOp.isFinished).to(beFalse());
+ expect(testOp.isCancelled).to(beFalse());
+
+ [testChoiceSet cancel];
+
+ expect(testConnectionManager.receivedRequests.lastObject).toNot(beAnInstanceOf([SDLCancelInteraction class]));
+
+ expect(testOp.isExecuting).to(beTrue());
+ expect(testOp.isFinished).to(beFalse());
+ expect(testOp.isCancelled).to(beTrue());
+ });
+ });
+
+ context(@"if the present is in progress", ^{
+ beforeEach(^{
+ // Move us past the preload
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:0 error:nil];
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:1 error:nil];
+ [testConnectionManager respondToRequestWithResponse:testGoodResponse requestNumber:2 error:nil];
+ [testConnectionManager respondToLastMultipleRequestsWithSuccess:YES];
+
+ // Move us past the SetGlobalProperties
+ SDLSetGlobalPropertiesResponse *sgpr = [[SDLSetGlobalPropertiesResponse alloc] init];
+ sgpr.success = @YES;
+ sgpr.resultCode = SDLResultSuccess;
+ [testConnectionManager respondToLastRequestWithResponse:sgpr];
+ });
+
+ it(@"should attempt to send a cancel interaction", ^{
+ expect(testOp.isExecuting).to(beTrue());
+ expect(testOp.isFinished).to(beFalse());
+ expect(testOp.isCancelled).to(beFalse());
+
+ [testChoiceSet cancel];
+
+ SDLCancelInteraction *lastRequest = testConnectionManager.receivedRequests.lastObject;
+ expect(lastRequest).to(beAnInstanceOf([SDLCancelInteraction class]));
+ expect(lastRequest.cancelID).to(equal(testCancelID));
+ expect(lastRequest.functionID).to(equal([SDLFunctionID.sharedInstance functionIdForName:SDLRPCFunctionNamePerformInteraction]));
+ });
+
+ context(@"If the cancel interaction was successful", ^{
+ __block SDLCancelInteractionResponse *testCancelInteractionResponse = [[SDLCancelInteractionResponse alloc] init];
+ beforeEach(^{
+ testCancelInteractionResponse.success = @YES;
+ testCancelInteractionResponse.resultCode = SDLResultSuccess;
+ [testChoiceSet cancel];
+ });
+
+ it(@"should finish with an error", ^{
+ // Respond to the cancel interaction, then the perform interaction
+ [testConnectionManager respondToLastRequestWithResponse:testCancelInteractionResponse];
+
+ SDLPerformInteractionResponse *pir = [[SDLPerformInteractionResponse alloc] init];
+ pir.success = @NO;
+ pir.resultCode = SDLResultAborted;
+ [testConnectionManager respondToRequestWithResponse:pir requestNumber:4 error:[NSError sdl_choiceSetManager_cancelled]];
+
+ // Try to reset the keyboard
+ expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLSetGlobalProperties class]));
+
+ SDLSetGlobalPropertiesResponse *sgpr = [[SDLSetGlobalPropertiesResponse alloc] init];
+ sgpr.success = @YES;
+ sgpr.resultCode = SDLResultSuccess;
+ [testConnectionManager respondToLastRequestWithResponse:sgpr];
+
+ OCMReject([testChoiceDelegate choiceSet:[OCMArg isNotNil] didSelectChoice:[OCMArg isNotNil] withSource:[OCMArg any] atRowIndex:0]);
+ OCMVerify([testChoiceDelegate choiceSet:[OCMArg isEqual:testChoiceSet] didReceiveError:[OCMArg isNotNil]]);
+ });
+ });
+
+ context(@"If the cancel interaction was not successful", ^{
+ __block NSError *testError = [NSError sdl_lifecycle_notConnectedError];
+ __block SDLCancelInteractionResponse *testCancelInteractionResponse = [[SDLCancelInteractionResponse alloc] init];
+
+ beforeEach(^{
+ testCancelInteractionResponse.success = @NO;
+ });
+
+ it(@"should error", ^{
+ OCMExpect([testChoiceDelegate choiceSet:[OCMArg any] didReceiveError:[OCMArg any]]);
+ OCMReject([testChoiceDelegate choiceSet:[OCMArg isEqual:testChoiceSet] didSelectChoice:[OCMArg isNotNil] withSource:[OCMArg isEqual:SDLTriggerSourceVoiceRecognition] atRowIndex:0]);
+ [testConnectionManager respondToLastRequestWithResponse:testCancelInteractionResponse error:testError];
+ });
+ });
+ });
+ });
+
+ context(@"if the operation has already finished", ^{
+ it(@"should not attempt to send a cancel interaction", ^{
+ [testOp finishOperation];
+
+ expect(testOp.isExecuting).to(beFalse());
+ expect(testOp.isFinished).to(beTrue());
+ expect(testOp.isCancelled).to(beFalse());
+
+ [testChoiceSet cancel];
+
+ SDLCancelInteraction *lastRequest = testConnectionManager.receivedRequests.lastObject;
+ expect(lastRequest).to(beNil());
+ });
+ });
+
+ context(@"if the operation has not started", ^{
+ beforeEach(^{
+ expect(testOp.isExecuting).to(beFalse());
+ expect(testOp.isFinished).to(beFalse());
+ expect(testOp.isCancelled).to(beFalse());
+
+ [testChoiceSet cancel];
+ });
+
+ it(@"should not attempt to send a cancel interaction", ^{
+ expect(testOp.isExecuting).to(beFalse());
+ expect(testOp.isFinished).to(beFalse());
+ expect(testOp.isCancelled).to(beTrue());
+
+ SDLCancelInteraction *lastRequest = testConnectionManager.receivedRequests.lastObject;
+ expect(lastRequest).to(beNil());
+ });
+
+ context(@"once the operation has started", ^{
+ beforeEach(^{
+ [testOp start];
+ });
+
+ it(@"immediately finish", ^{
+ expect(testConnectionManager.receivedRequests).to(haveCount(0));
+ expect(testOp.isExecuting).to(beFalse());
+ expect(testOp.isFinished).to(beTrue());
+ expect(testOp.isCancelled).to(beTrue());
+ });
+
+ it(@"should finish", ^{
+ expect(testOp.isExecuting).toEventually(beFalse());
+ expect(testOp.isFinished).toEventually(beTrue());
+ expect(testOp.isCancelled).toEventually(beTrue());
+ });
+ });
+ });
+ });
+
+ context(@"Head unit does not support the `CancelInteraction` RPC", ^{
+ beforeEach(^{
+ SDLVersion *unsupportedVersion = [SDLVersion versionWithMajor:5 minor:1 patch:0];
+ id globalMock = OCMPartialMock([SDLGlobals sharedGlobals]);
+ OCMStub([globalMock rpcVersion]).andReturn(unsupportedVersion);
+ });
+
+ it(@"should not attempt to send a cancel interaction if the operation is executing", ^{
+ [testOp start];
+
+ expect(testOp.isExecuting).to(beTrue());
+ expect(testOp.isFinished).to(beFalse());
+ expect(testOp.isCancelled).to(beFalse());
+
+ [testChoiceSet cancel];
+
+ SDLCancelInteraction *lastRequest = testConnectionManager.receivedRequests.lastObject;
+ expect(lastRequest).toNot(beAnInstanceOf([SDLCancelInteraction class]));
+ });
+
+ it(@"should cancel the operation if it has not yet been run", ^{
+ expect(testOp.isExecuting).to(beFalse());
+ expect(testOp.isFinished).to(beFalse());
+ expect(testOp.isCancelled).to(beFalse());
+
+ [testChoiceSet cancel];
+
+ SDLCancelInteraction *lastRequest = testConnectionManager.receivedRequests.lastObject;
+ expect(lastRequest).to(beNil());
+
+ expect(testOp.isExecuting).to(beFalse());
+ expect(testOp.isFinished).to(beFalse());
+ expect(testOp.isCancelled).to(beTrue());
+ });
+ });
+ });
+ });
+});
+
+QuickSpecEnd
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLPreloadPresentChoicesOperationUtilitiesSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLPreloadPresentChoicesOperationUtilitiesSpec.m
new file mode 100644
index 000000000..b09d7a3e2
--- /dev/null
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLPreloadPresentChoicesOperationUtilitiesSpec.m
@@ -0,0 +1,504 @@
+//
+// SDLPreloadPresentChoiceSetOperationUtilitiesSpec.m
+// SmartDeviceLinkTests
+//
+// Created by Joel Fischer on 8/27/21.
+// Copyright © 2021 smartdevicelink. All rights reserved.
+//
+
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+#import <OCMock/OCMock.h>
+
+#import "SDLPreloadPresentChoicesOperationUtilities.h"
+
+#import "SDLChoiceCell.h"
+#import "SDLChoiceSet.h"
+#import "SDLGlobals.h"
+#import "SDLImageField+ScreenManagerExtensions.h"
+#import "SDLTextField+ScreenManagerExtensions.h"
+#import "SDLVersion.h"
+#import "SDLWindowCapability+ScreenManagerExtensions.h"
+
+@interface SDLChoiceCell()
+
+@property (assign, nonatomic) UInt16 choiceId;
+
+@end
+
+@interface SDLPreloadPresentChoicesOperationUtilitiesSpec : QuickSpec @end
+@implementation SDLPreloadPresentChoicesOperationUtilitiesSpec
+
+- (NSOrderedSet<SDLChoiceCell *> *)sdl_cellsToLoadWithCount:(UInt16)count {
+ NSMutableOrderedSet<SDLChoiceCell *> *mutableCells = [NSMutableOrderedSet orderedSetWithCapacity:count];
+ for (NSUInteger i = 1; i <= count; i++) {
+ [mutableCells addObject:[[SDLChoiceCell alloc] initWithText:[NSString stringWithFormat:@"Cell %lu", i]]];
+ }
+
+ return mutableCells.copy;
+}
+
+- (NSSet<SDLChoiceCell *> *)sdl_loadedCellsWithStartNum:(UInt16)startNum endNum:(UInt16)endNum {
+ NSMutableSet<SDLChoiceCell *> *mutableCells = [NSMutableSet setWithCapacity:(endNum - startNum)];
+ for (NSUInteger i = startNum; i <= endNum; i++) {
+ SDLChoiceCell *cell = [[SDLChoiceCell alloc] initWithText:[NSString stringWithFormat:@"Loaded Cell %lu", i]];
+ cell.choiceId = (UInt16)i;
+
+ [mutableCells addObject:cell];
+ }
+
+ return mutableCells.copy;
+}
+
+- (void)spec {
+ __block NSOrderedSet<SDLChoiceCell *> *testCellsToLoad = nil;
+ __block NSSet<SDLChoiceCell *> *testLoadedCells = nil;
+
+ describe(@"assigning ids", ^{
+ context(@"when we're on the first loop of assigning ids", ^{
+ beforeEach(^{
+ SDLPreloadPresentChoicesOperationUtilities.reachedMaxId = NO;
+ SDLPreloadPresentChoicesOperationUtilities.choiceId = 1;
+ });
+
+ context(@"when there's no ids already set", ^{
+ beforeEach(^{
+ testLoadedCells = [NSSet set];
+ testCellsToLoad = [self sdl_cellsToLoadWithCount:50];
+ });
+
+ it(@"should set ids starting at 0", ^{
+ [SDLPreloadPresentChoicesOperationUtilities assignIdsToCells:testCellsToLoad loadedCells:testLoadedCells];
+ expect(testCellsToLoad.count).to(equal(50));
+ for (NSUInteger i = 0; i < testCellsToLoad.count; i++) {
+ expect((NSUInteger)testCellsToLoad[i].choiceId).to(equal(i + 1));
+ }
+ });
+ });
+
+ context(@"when ids are already set", ^{
+ context(@"when not reaching the max value", ^{
+ beforeEach(^{
+ SDLPreloadPresentChoicesOperationUtilities.choiceId = 100;
+
+ testLoadedCells = [NSSet set];
+ testCellsToLoad = [self sdl_cellsToLoadWithCount:50];
+ });
+
+ it(@"should set ids starting at the next id", ^{
+ [SDLPreloadPresentChoicesOperationUtilities assignIdsToCells:testCellsToLoad loadedCells:testLoadedCells];
+ expect(testCellsToLoad.count).to(equal(50));
+ for (NSUInteger i = 0; i < testCellsToLoad.count; i++) {
+ expect((NSUInteger)testCellsToLoad[i].choiceId).to(equal(i + 100));
+ }
+ expect(SDLPreloadPresentChoicesOperationUtilities.reachedMaxId).to(beFalse());
+ });
+ });
+
+ context(@"when reaching the max value", ^{
+ beforeEach(^{
+ SDLPreloadPresentChoicesOperationUtilities.choiceId = 65500;
+
+ testLoadedCells = [self sdl_loadedCellsWithStartNum:0 endNum:65499];
+ testCellsToLoad = [self sdl_cellsToLoadWithCount:35];
+ });
+
+ it(@"should set the reachedMaxId BOOL and not loop back over yet", ^{
+ [SDLPreloadPresentChoicesOperationUtilities assignIdsToCells:testCellsToLoad loadedCells:testLoadedCells];
+ expect(testCellsToLoad.count).to(equal(35));
+ for (NSUInteger i = 0; i < testCellsToLoad.count; i++) {
+ expect((NSUInteger)testCellsToLoad[i].choiceId).to(equal(i + 65500));
+ }
+ expect(SDLPreloadPresentChoicesOperationUtilities.reachedMaxId).to(beFalse());
+ });
+ });
+ });
+ });
+
+ context(@"on subsequent loops of assigning ids", ^{
+ beforeEach(^{
+ SDLPreloadPresentChoicesOperationUtilities.reachedMaxId = YES;
+ SDLPreloadPresentChoicesOperationUtilities.choiceId = 1;
+ });
+
+ context(@"when loadedCells is not full", ^{
+ context(@"when loaded cells are contiguous at the beginning", ^{
+ beforeEach(^{
+ SDLPreloadPresentChoicesOperationUtilities.choiceId = 99;
+
+ testLoadedCells = [self sdl_loadedCellsWithStartNum:0 endNum:99];
+ testCellsToLoad = [self sdl_cellsToLoadWithCount:35];
+ });
+
+ it(@"should assign ids after those", ^{
+ [SDLPreloadPresentChoicesOperationUtilities assignIdsToCells:testCellsToLoad loadedCells:testLoadedCells];
+ expect(testCellsToLoad.count).to(equal(35));
+ for (NSUInteger i = 0; i < testCellsToLoad.count; i++) {
+ expect((NSUInteger)testCellsToLoad[i].choiceId).to(equal(i + 100));
+ }
+ expect(SDLPreloadPresentChoicesOperationUtilities.reachedMaxId).to(beTrue());
+ });
+ });
+
+ context(@"when those items are contiguous in the middle so that assigning cells overlap", ^{
+ beforeEach(^{
+ SDLPreloadPresentChoicesOperationUtilities.choiceId = 10;
+
+ testLoadedCells = [self sdl_loadedCellsWithStartNum:3 endNum:10];
+ testCellsToLoad = [self sdl_cellsToLoadWithCount:13];
+ });
+
+ it(@"should start assigning from the last used id", ^{
+ [SDLPreloadPresentChoicesOperationUtilities assignIdsToCells:testCellsToLoad loadedCells:testLoadedCells];
+ expect(testCellsToLoad.count).to(equal(13));
+ for (NSUInteger i = 0; i < testCellsToLoad.count; i++) {
+ expect((NSUInteger)testCellsToLoad[i].choiceId).to(equal(i + 11));
+ }
+ expect(SDLPreloadPresentChoicesOperationUtilities.reachedMaxId).to(beTrue());
+ });
+ });
+
+ context(@"when there are items scattered and overlapping setting cells", ^{
+ beforeEach(^{
+ SDLPreloadPresentChoicesOperationUtilities.choiceId = 10;
+
+ testLoadedCells = [self sdl_loadedCellsWithStartNum:3 endNum:10];
+ NSSet<SDLChoiceCell *> *secondLoadedCells = [self sdl_loadedCellsWithStartNum:50 endNum:55];
+ testLoadedCells = [testLoadedCells setByAddingObjectsFromSet:secondLoadedCells];
+
+ testCellsToLoad = [self sdl_cellsToLoadWithCount:10];
+ });
+
+ it(@"start from the last used id", ^{
+ [SDLPreloadPresentChoicesOperationUtilities assignIdsToCells:testCellsToLoad loadedCells:testLoadedCells];
+ expect(testCellsToLoad.count).to(equal(10));
+ for (NSUInteger i = 0; i < testCellsToLoad.count; i++) {
+ expect((NSUInteger)testCellsToLoad[i].choiceId).to(equal(i + 56));
+ }
+ expect(SDLPreloadPresentChoicesOperationUtilities.reachedMaxId).to(beTrue());
+ });
+ });
+
+ context(@"when not enough open ids are available", ^{
+ beforeEach(^{
+ SDLPreloadPresentChoicesOperationUtilities.choiceId = 10;
+
+ testLoadedCells = [self sdl_loadedCellsWithStartNum:3 endNum:10];
+ NSSet<SDLChoiceCell *> *secondLoadedCells = [self sdl_loadedCellsWithStartNum:12 endNum:65533];
+ testLoadedCells = [testLoadedCells setByAddingObjectsFromSet:secondLoadedCells];
+
+ testCellsToLoad = [self sdl_cellsToLoadWithCount:10];
+ });
+ it(@"should assign what it can and the rest should be UINT16_MAX", ^{
+ [SDLPreloadPresentChoicesOperationUtilities assignIdsToCells:testCellsToLoad loadedCells:testLoadedCells];
+ expect(testCellsToLoad.count).to(equal(10));
+
+ expect((NSUInteger)testCellsToLoad[0].choiceId).to(equal(65534));
+ expect((NSUInteger)testCellsToLoad[1].choiceId).to(equal(65535));
+ expect((NSUInteger)testCellsToLoad[2].choiceId).to(equal(0));
+ expect((NSUInteger)testCellsToLoad[3].choiceId).to(equal(1));
+ expect((NSUInteger)testCellsToLoad[4].choiceId).to(equal(2));
+ expect((NSUInteger)testCellsToLoad[5].choiceId).to(equal(11));
+ expect((NSUInteger)testCellsToLoad[6].choiceId).to(equal(65535));
+ expect((NSUInteger)testCellsToLoad[7].choiceId).to(equal(65535));
+ expect((NSUInteger)testCellsToLoad[8].choiceId).to(equal(65535));
+ expect((NSUInteger)testCellsToLoad[9].choiceId).to(equal(65535));
+
+ expect(SDLPreloadPresentChoicesOperationUtilities.reachedMaxId).to(beTrue());
+ });
+ });
+ });
+
+ context(@"when loadedCells is full", ^{
+ beforeEach(^{
+ SDLPreloadPresentChoicesOperationUtilities.choiceId = 65535;
+
+ testLoadedCells = [self sdl_loadedCellsWithStartNum:0 endNum:65535];
+ testCellsToLoad = [self sdl_cellsToLoadWithCount:10];
+ });
+
+ it(@"should set all ids to UINT16_MAX", ^{
+ [SDLPreloadPresentChoicesOperationUtilities assignIdsToCells:testCellsToLoad loadedCells:testLoadedCells];
+ expect(testCellsToLoad.count).to(equal(10));
+ for (NSUInteger i = 0; i < testCellsToLoad.count; i++) {
+ expect((NSUInteger)testCellsToLoad[i].choiceId).to(equal(65535));
+ }
+ expect(SDLPreloadPresentChoicesOperationUtilities.reachedMaxId).to(beTrue());
+ });
+ });
+ });
+ });
+
+ describe(@"making cells unique", ^{
+ __block SDLWindowCapability *enabledWindowCapability = nil;
+ __block SDLWindowCapability *primaryTextOnlyCapability = nil;
+
+ beforeEach(^{
+ enabledWindowCapability = [[SDLWindowCapability alloc] init];
+ enabledWindowCapability.textFields = @[
+ [[SDLTextField alloc] initWithName:SDLTextFieldNameMenuName characterSet:SDLCharacterSetUtf8 width:500 rows:1],
+ [[SDLTextField alloc] initWithName:SDLTextFieldNameSecondaryText characterSet:SDLCharacterSetUtf8 width:500 rows:1],
+ [[SDLTextField alloc] initWithName:SDLTextFieldNameTertiaryText characterSet:SDLCharacterSetUtf8 width:500 rows:1]
+ ];
+ enabledWindowCapability.imageFields = @[
+ [[SDLImageField alloc] initWithName:SDLImageFieldNameChoiceImage imageTypeSupported:@[SDLFileTypePNG] imageResolution:nil],
+ [[SDLImageField alloc] initWithName:SDLImageFieldNameChoiceSecondaryImage imageTypeSupported:@[SDLFileTypePNG] imageResolution:nil]
+ ];
+ primaryTextOnlyCapability = [[SDLWindowCapability alloc] init];
+ primaryTextOnlyCapability.textFields = @[
+ [[SDLTextField alloc] initWithName:SDLTextFieldNameMenuName characterSet:SDLCharacterSetUtf8 width:500 rows:1],
+ ];
+
+ testLoadedCells = [NSSet set];
+ });
+
+ context(@"at RPC v7.1", ^{
+ beforeEach(^{
+ [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithMajor:7 minor:1 patch:0];
+ });
+
+ context(@"when cells are unique except when stripped", ^{
+ beforeEach(^{
+ testCellsToLoad = [NSOrderedSet orderedSetWithArray:@[
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" secondaryText:@"Unique 1" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" secondaryText:@"Unique 2" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" secondaryText:@"Unique 3" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Unique 1" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil]
+ ]];
+ });
+
+ context(@"with full window capability", ^{
+ beforeEach(^{
+ [SDLPreloadPresentChoicesOperationUtilities makeCellsToUploadUnique:testCellsToLoad.mutableCopy basedOnLoadedCells:testLoadedCells.mutableCopy windowCapability:enabledWindowCapability];
+ });
+
+ it(@"should not set unique titles", ^{
+ expect(testCellsToLoad[0].uniqueText).to(equal(testCellsToLoad[0].text));
+ expect(testCellsToLoad[1].uniqueText).to(equal(testCellsToLoad[1].text));
+ expect(testCellsToLoad[2].uniqueText).to(equal(testCellsToLoad[2].text));
+ expect(testCellsToLoad[3].uniqueText).to(equal(testCellsToLoad[3].text));
+ });
+ });
+
+ context(@"with primary text only capability", ^{
+ beforeEach(^{
+ [SDLPreloadPresentChoicesOperationUtilities makeCellsToUploadUnique:testCellsToLoad.mutableCopy basedOnLoadedCells:testLoadedCells.mutableCopy windowCapability:primaryTextOnlyCapability];
+ });
+
+ it(@"should set unique titles", ^{
+ expect(testCellsToLoad[0].uniqueText).to(equal(testCellsToLoad[0].text));
+ expect(testCellsToLoad[1].uniqueText).toNot(equal(testCellsToLoad[1].text));
+ expect(testCellsToLoad[2].uniqueText).toNot(equal(testCellsToLoad[2].text));
+ expect(testCellsToLoad[3].uniqueText).to(equal(testCellsToLoad[3].text));
+ });
+ });
+ });
+
+ context(@"when cells are unique", ^{
+ beforeEach(^{
+ testCellsToLoad = [NSOrderedSet orderedSetWithArray:@[
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 3" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 4" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil]
+ ]];
+
+ [SDLPreloadPresentChoicesOperationUtilities makeCellsToUploadUnique:testCellsToLoad.mutableCopy basedOnLoadedCells:testLoadedCells.mutableCopy windowCapability:enabledWindowCapability];
+ });
+
+ it(@"should not set unique titles", ^{
+ expect(testCellsToLoad[0].uniqueText).to(equal(testCellsToLoad[0].text));
+ expect(testCellsToLoad[1].uniqueText).to(equal(testCellsToLoad[1].text));
+ expect(testCellsToLoad[2].uniqueText).to(equal(testCellsToLoad[2].text));
+ expect(testCellsToLoad[3].uniqueText).to(equal(testCellsToLoad[3].text));
+ });
+ });
+
+ context(@"when loaded cells match the cells when stripped", ^{
+ beforeEach(^{
+ testLoadedCells = [NSSet setWithArray:@[
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1"],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 2"],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 3"],
+ ]];
+
+ testCellsToLoad = [NSOrderedSet orderedSetWithArray:@[
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" secondaryText:@"Unique" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Unique" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" secondaryText:@"Unique 2" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 4" secondaryText:@"Unique" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil]
+ ]];
+ });
+
+ context(@"with full window capability", ^{
+ beforeEach(^{
+ [SDLPreloadPresentChoicesOperationUtilities makeCellsToUploadUnique:testCellsToLoad.mutableCopy basedOnLoadedCells:testLoadedCells.mutableCopy windowCapability:enabledWindowCapability];
+ });
+
+ it(@"should not make unique text", ^{
+ expect(testCellsToLoad[0].uniqueText).to(equal(testCellsToLoad[0].text));
+ expect(testCellsToLoad[1].uniqueText).to(equal(testCellsToLoad[1].text));
+ expect(testCellsToLoad[2].uniqueText).to(equal(testCellsToLoad[2].text));
+ expect(testCellsToLoad[3].uniqueText).to(equal(testCellsToLoad[3].text));
+ });
+ });
+
+ context(@"with primary text only capability", ^{
+ beforeEach(^{
+ [SDLPreloadPresentChoicesOperationUtilities makeCellsToUploadUnique:testCellsToLoad.mutableCopy basedOnLoadedCells:testLoadedCells.mutableCopy windowCapability:primaryTextOnlyCapability];
+ });
+
+ it(@"should not make unique text", ^{
+ expect(testCellsToLoad[0].uniqueText).toNot(equal(testCellsToLoad[0].text));
+ expect(testCellsToLoad[1].uniqueText).toNot(equal(testCellsToLoad[1].text));
+ expect(testCellsToLoad[2].uniqueText).toNot(equal(testCellsToLoad[2].text));
+ expect(testCellsToLoad[3].uniqueText).to(equal(testCellsToLoad[3].text));
+ });
+ });
+ });
+ });
+
+ context(@"below RPC v7.1", ^{
+ beforeEach(^{
+ [SDLGlobals sharedGlobals].rpcVersion = [SDLVersion versionWithMajor:7 minor:0 patch:0];
+ });
+
+ context(@"when cells are unique except when stripped", ^{
+ beforeEach(^{
+ testCellsToLoad = [NSOrderedSet orderedSetWithArray:@[
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" secondaryText:@"Unique 1" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" secondaryText:@"Unique 2" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" secondaryText:@"Unique 3" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Unique 1" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil]
+ ]];
+
+ [SDLPreloadPresentChoicesOperationUtilities makeCellsToUploadUnique:testCellsToLoad.mutableCopy basedOnLoadedCells:testLoadedCells.mutableCopy windowCapability:enabledWindowCapability];
+ });
+
+ it(@"should set unique titles except the first and last", ^{
+ expect(testCellsToLoad[0].uniqueText).to(equal(testCellsToLoad[0].text));
+ expect(testCellsToLoad[1].uniqueText).toNot(equal(testCellsToLoad[1].text));
+ expect(testCellsToLoad[2].uniqueText).toNot(equal(testCellsToLoad[2].text));
+ expect(testCellsToLoad[3].uniqueText).to(equal(testCellsToLoad[3].text));
+ });
+ });
+
+ context(@"when cells are unique", ^{
+ beforeEach(^{
+ testCellsToLoad = [NSOrderedSet orderedSetWithArray:@[
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 3" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 4" secondaryText:nil tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil]
+ ]];
+
+ [SDLPreloadPresentChoicesOperationUtilities makeCellsToUploadUnique:testCellsToLoad.mutableCopy basedOnLoadedCells:testLoadedCells.mutableCopy windowCapability:enabledWindowCapability];
+ });
+
+ it(@"should not set unique titles", ^{
+ expect(testCellsToLoad[0].uniqueText).to(equal(testCellsToLoad[0].text));
+ expect(testCellsToLoad[1].uniqueText).to(equal(testCellsToLoad[1].text));
+ expect(testCellsToLoad[2].uniqueText).to(equal(testCellsToLoad[2].text));
+ expect(testCellsToLoad[3].uniqueText).to(equal(testCellsToLoad[3].text));
+ });
+ });
+
+ context(@"when loaded cells match the cells when stripped", ^{
+ beforeEach(^{
+ testLoadedCells = [NSSet setWithArray:@[
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1"],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 2"],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 3"],
+ ]];
+
+ testCellsToLoad = [NSOrderedSet orderedSetWithArray:@[
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" secondaryText:@"Unique" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 2" secondaryText:@"Unique" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1" secondaryText:@"Unique 2" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 4" secondaryText:@"Unique" tertiaryText:nil voiceCommands:nil artwork:nil secondaryArtwork:nil]
+ ]];
+ });
+
+ context(@"with full window capability", ^{
+ beforeEach(^{
+ [SDLPreloadPresentChoicesOperationUtilities makeCellsToUploadUnique:testCellsToLoad.mutableCopy basedOnLoadedCells:testLoadedCells.mutableCopy windowCapability:enabledWindowCapability];
+ });
+
+ it(@"should make unique text", ^{
+ expect(testCellsToLoad[0].uniqueText).toNot(equal(testCellsToLoad[0].text));
+ expect(testCellsToLoad[1].uniqueText).toNot(equal(testCellsToLoad[1].text));
+ expect(testCellsToLoad[2].uniqueText).toNot(equal(testCellsToLoad[2].text));
+ expect(testCellsToLoad[3].uniqueText).to(equal(testCellsToLoad[3].text));
+ });
+ });
+
+ context(@"with primary text only capability", ^{
+ beforeEach(^{
+ [SDLPreloadPresentChoicesOperationUtilities makeCellsToUploadUnique:testCellsToLoad.mutableCopy basedOnLoadedCells:testLoadedCells.mutableCopy windowCapability:primaryTextOnlyCapability];
+ });
+
+ it(@"should not make unique text", ^{
+ expect(testCellsToLoad[0].uniqueText).toNot(equal(testCellsToLoad[0].text));
+ expect(testCellsToLoad[1].uniqueText).toNot(equal(testCellsToLoad[1].text));
+ expect(testCellsToLoad[2].uniqueText).toNot(equal(testCellsToLoad[2].text));
+ expect(testCellsToLoad[3].uniqueText).to(equal(testCellsToLoad[3].text));
+ });
+ });
+ });
+ });
+ });
+
+ describe(@"updating a choice set based on loaded cells and cells to upload", ^{
+ __block SDLChoiceSet *testChoiceSet = nil;
+ __block NSArray<SDLChoiceCell *> *basicChoiceCells = nil;
+ __block NSMutableArray<SDLChoiceCell *> *testLoadedCellsArray = nil;
+
+ beforeEach(^{
+ basicChoiceCells = @[
+ [[SDLChoiceCell alloc] initWithText:@"Cell 1"],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 2"],
+ [[SDLChoiceCell alloc] initWithText:@"Cell 3"],
+ ];
+
+ // Has all three cells with no ids
+ testChoiceSet = [[SDLChoiceSet alloc] init];
+ testChoiceSet.choices = basicChoiceCells;
+
+ // Has all three cells with different ids
+ testCellsToLoad = [NSOrderedSet orderedSetWithArray:basicChoiceCells range:NSMakeRange(0, 3) copyItems:YES];
+ for (NSUInteger i = 0; i < testCellsToLoad.count; i++) {
+ testCellsToLoad[i].choiceId = i;
+ }
+
+ // Loaded cells has first two items with different ids
+ testLoadedCellsArray = [[NSMutableArray alloc] initWithArray:basicChoiceCells copyItems:YES];
+ [testLoadedCellsArray removeLastObject];
+ for (NSUInteger i = 0; i < testLoadedCellsArray.count; i++) {
+ testLoadedCellsArray[i].choiceId = i + 10;
+ }
+ testLoadedCells = [NSSet setWithArray:testLoadedCellsArray];
+ });
+
+ context(@"when there are no loaded cells", ^{
+ it(@"should have all cells the same as cells to upload", ^{
+ [SDLPreloadPresentChoicesOperationUtilities updateChoiceSet:testChoiceSet withLoadedCells:[NSSet set] cellsToUpload:testCellsToLoad.set];
+
+ for (NSUInteger i = 0; i < testChoiceSet.choices.count; i++) {
+ expect((NSUInteger)testChoiceSet.choices[i].choiceId).to(equal(testCellsToLoad[i].choiceId));
+ }
+ });
+ });
+
+ context(@"when some loaded cells match", ^{
+ it(@"should use the loaded cells when possible", ^{
+ [SDLPreloadPresentChoicesOperationUtilities updateChoiceSet:testChoiceSet withLoadedCells:testLoadedCells cellsToUpload:testCellsToLoad.set];
+
+ expect((NSUInteger)testChoiceSet.choices[0].choiceId).to(equal(testLoadedCellsArray[0].choiceId));
+ expect((NSUInteger)testChoiceSet.choices[1].choiceId).to(equal(testLoadedCellsArray[1].choiceId));
+ expect((NSUInteger)testChoiceSet.choices[2].choiceId).to(equal(testCellsToLoad[2].choiceId));
+ });
+ });
+ });
+}
+
+@end
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLPresentChoiceSetOperationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLPresentChoiceSetOperationSpec.m
deleted file mode 100644
index f918c6909..000000000
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLPresentChoiceSetOperationSpec.m
+++ /dev/null
@@ -1,549 +0,0 @@
-#import <Quick/Quick.h>
-#import <Nimble/Nimble.h>
-#import <OCMock/OCMock.h>
-
-#import "SDLPresentChoiceSetOperation.h"
-
-#import "SDLCancelInteraction.h"
-#import "SDLCancelInteractionResponse.h"
-#import "SDLChoiceCell.h"
-#import "SDLChoiceSet.h"
-#import "SDLChoiceSetDelegate.h"
-#import "SDLError.h"
-#import "SDLFunctionID.h"
-#import "SDLKeyboardDelegate.h"
-#import "SDLOnKeyboardInput.h"
-#import "SDLKeyboardProperties.h"
-#import "SDLPerformInteraction.h"
-#import "SDLPerformInteractionResponse.h"
-#import "SDLRPCNotificationNotification.h"
-#import "SDLGlobals.h"
-#import "SDLSetGlobalProperties.h"
-#import "SDLSetGlobalPropertiesResponse.h"
-#import "SDLVersion.h"
-#import "TestConnectionManager.h"
-
-@interface SDLChoiceSet()
-
-@property (nullable, copy, nonatomic) SDLChoiceSetCanceledHandler canceledHandler;
-
-@end
-
-QuickSpecBegin(SDLPresentChoiceSetOperationSpec)
-
-describe(@"present choice operation", ^{
- __block TestConnectionManager *testConnectionManager = nil;
- __block SDLPresentChoiceSetOperation *testOp = nil;
-
- __block SDLInteractionMode testInteractionMode = SDLInteractionModeBoth;
- __block SDLChoiceSet *testChoiceSet = nil;
- __block id<SDLChoiceSetDelegate> testChoiceDelegate = nil;
- __block NSArray<SDLChoiceCell *> *testChoices = nil;
- __block int testCancelID = 98;
-
- __block id<SDLKeyboardDelegate> testKeyboardDelegate = nil;
- __block SDLKeyboardProperties *testKeyboardProperties = nil;
-
- __block BOOL hasCalledOperationCompletionHandler = NO;
- __block NSError *resultError = nil;
- __block SDLWindowCapability *windowCapability = nil;
-
- beforeEach(^{
- resultError = nil;
- hasCalledOperationCompletionHandler = NO;
-
- testConnectionManager = [[TestConnectionManager alloc] init];
-
- testChoiceDelegate = OCMProtocolMock(@protocol(SDLChoiceSetDelegate));
- SDLChoiceCell *cell1 = [[SDLChoiceCell alloc] initWithText:@"Cell 1"];
- testChoices = @[cell1];
- testChoiceSet = [[SDLChoiceSet alloc] initWithTitle:@"Test Title" delegate:testChoiceDelegate layout:SDLChoiceSetLayoutTiles timeout:13 initialPromptString:@"Test initial prompt" timeoutPromptString:@"Test timeout prompt" helpPromptString:@"Test help prompt" vrHelpList:nil choices:testChoices];
-
- windowCapability = [[SDLWindowCapability alloc] init];
- testKeyboardDelegate = OCMProtocolMock(@protocol(SDLKeyboardDelegate));
- OCMStub([testKeyboardDelegate customKeyboardConfiguration]).andReturn(nil);
- testKeyboardProperties = [[SDLKeyboardProperties alloc] initWithLanguage:SDLLanguageArSa keyboardLayout:SDLKeyboardLayoutAZERTY keypressMode:SDLKeypressModeResendCurrentEntry limitedCharacterList:nil autoCompleteList:nil maskInputCharacters:nil customKeys:nil];
- });
-
- it(@"should have a priority of 'normal'", ^{
- testOp = [[SDLPresentChoiceSetOperation alloc] init];
-
- expect(@(testOp.queuePriority)).to(equal(@(NSOperationQueuePriorityNormal)));
- });
-
- describe(@"running a non-searchable choice set operation", ^{
- beforeEach(^{
- testOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:testConnectionManager choiceSet:testChoiceSet mode:testInteractionMode keyboardProperties:nil keyboardDelegate:nil cancelID:testCancelID windowCapability:windowCapability];
- testOp.completionBlock = ^{
- hasCalledOperationCompletionHandler = YES;
- };
- [testOp start];
- });
-
- it(@"should not update global keyboard properties", ^{
- expect(testConnectionManager.receivedRequests.lastObject).toNot(beAnInstanceOf([SDLSetGlobalProperties class]));
- });
-
- describe(@"presenting the choice set", ^{
- it(@"should send the perform interaction", ^{
- expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLPerformInteraction class]));
- SDLPerformInteraction *request = testConnectionManager.receivedRequests.lastObject;
- expect(request.initialText).to(equal(testChoiceSet.title));
- expect(request.initialPrompt).to(equal(testChoiceSet.initialPrompt));
- expect(request.interactionMode).to(equal(testInteractionMode));
- expect(request.interactionLayout).to(equal(SDLLayoutModeIconOnly));
- expect(request.timeoutPrompt).to(equal(testChoiceSet.timeoutPrompt));
- expect(request.helpPrompt).to(equal(testChoiceSet.helpPrompt));
- expect(request.timeout).to(equal(testChoiceSet.timeout * 1000));
- expect(request.vrHelp).to(beNil());
- expect(request.interactionChoiceSetIDList).to(equal(@[@65535]));
- expect(request.cancelID).to(equal(testCancelID));
- });
-
- describe(@"after a perform interaction response", ^{
- __block UInt16 responseChoiceId = UINT16_MAX;
- __block SDLTriggerSource responseTriggerSource = SDLTriggerSourceMenu;
-
- beforeEach(^{
- SDLPerformInteractionResponse *response = [[SDLPerformInteractionResponse alloc] init];
- response.success = @YES;
- response.choiceID = @(responseChoiceId);
- response.triggerSource = responseTriggerSource;
-
- [testConnectionManager respondToLastRequestWithResponse:response];
- });
-
- it(@"should not reset the keyboard properties and should be finished", ^{
- expect(testConnectionManager.receivedRequests.lastObject).toNot(beAnInstanceOf([SDLSetGlobalProperties class]));
- expect(hasCalledOperationCompletionHandler).toEventually(beTrue());
- expect(testOp.isFinished).to(beTrue());
- expect(testOp.selectedCell).to(equal(testChoices.firstObject));
- expect(testOp.selectedTriggerSource).to(equal(responseTriggerSource));
- });
- });
- });
-
- describe(@"Canceling the choice set", ^{
- __block SDLPresentChoiceSetOperation *testCancelOp = nil;
-
- beforeEach(^{
- testCancelOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:testConnectionManager choiceSet:testChoiceSet mode:testInteractionMode keyboardProperties:nil keyboardDelegate:nil cancelID:testCancelID windowCapability:windowCapability];
- testCancelOp.completionBlock = ^{
- hasCalledOperationCompletionHandler = YES;
- };
- });
-
- context(@"Head unit supports the `CancelInteration` RPC", ^{
- beforeEach(^{
- SDLVersion *supportedVersion = [SDLVersion versionWithMajor:6 minor:0 patch:0];
- id globalMock = OCMPartialMock([SDLGlobals sharedGlobals]);
- OCMStub([globalMock rpcVersion]).andReturn(supportedVersion);
- });
-
- context(@"If the operation is executing", ^{
- beforeEach(^{
- [testCancelOp start];
-
- expect(testCancelOp.isExecuting).to(beTrue());
- expect(testCancelOp.isFinished).to(beFalse());
- expect(testCancelOp.isCancelled).to(beFalse());
-
- [testChoiceSet cancel];
- });
-
- it(@"should attempt to send a cancel interaction", ^{
- SDLCancelInteraction *lastRequest = testConnectionManager.receivedRequests.lastObject;
- expect(lastRequest).to(beAnInstanceOf([SDLCancelInteraction class]));
- expect(lastRequest.cancelID).to(equal(testCancelID));
- expect(lastRequest.functionID).to(equal([SDLFunctionID.sharedInstance functionIdForName:SDLRPCFunctionNamePerformInteraction]));
- });
-
- context(@"If the cancel interaction was successful", ^{
- beforeEach(^{
- SDLCancelInteractionResponse *testCancelInteractionResponse = [[SDLCancelInteractionResponse alloc] init];
- testCancelInteractionResponse.success = @YES;
- [testConnectionManager respondToLastRequestWithResponse:testCancelInteractionResponse];
- });
-
- it(@"should not error", ^{
- expect(testCancelOp.error).to(beNil());
- });
-
- it(@"should not finish", ^{
- expect(hasCalledOperationCompletionHandler).to(beFalse());
- expect(testCancelOp.isExecuting).to(beTrue());
- expect(testCancelOp.isFinished).to(beFalse());
- expect(testCancelOp.isCancelled).to(beFalse());
- });
- });
-
- context(@"If the cancel interaction was not successful", ^{
- __block NSError *testError = [NSError sdl_lifecycle_notConnectedError];
-
- beforeEach(^{
- SDLCancelInteractionResponse *testCancelInteractionResponse = [[SDLCancelInteractionResponse alloc] init];
- testCancelInteractionResponse.success = @NO;
- [testConnectionManager respondToLastRequestWithResponse:testCancelInteractionResponse error:testError];
- });
-
- it(@"should error", ^{
- expect(testCancelOp.error).to(equal(testError));
- });
-
- it(@"should not finish", ^{
- expect(hasCalledOperationCompletionHandler).to(beFalse());
- expect(testCancelOp.isExecuting).to(beTrue());
- expect(testCancelOp.isFinished).to(beFalse());
- expect(testCancelOp.isCancelled).to(beFalse());
- });
- });
- });
-
- context(@"If the operation has already finished", ^{
- beforeEach(^{
- [testCancelOp finishOperation];
-
- expect(testCancelOp.isExecuting).to(beFalse());
- expect(testCancelOp.isFinished).to(beTrue());
- expect(testCancelOp.isCancelled).to(beFalse());
-
- [testChoiceSet cancel];
- });
-
- it(@"should not attempt to send a cancel interaction", ^{
- SDLCancelInteraction *lastRequest = testConnectionManager.receivedRequests.lastObject;
- expect(lastRequest).toNot(beAnInstanceOf([SDLCancelInteraction class]));
- });
- });
-
- context(@"If the started operation has been canceled", ^{
- beforeEach(^{
- [testCancelOp start];
- [testCancelOp cancel];
-
- expect(testCancelOp.isExecuting).to(beTrue());
- expect(testCancelOp.isFinished).to(beFalse());
- expect(testCancelOp.isCancelled).to(beTrue());
-
- [testChoiceSet cancel];
- });
-
- it(@"should not attempt to send a cancel interaction", ^{
- SDLCancelInteraction *lastRequest = testConnectionManager.receivedRequests.lastObject;
- expect(lastRequest).toNot(beAnInstanceOf([SDLCancelInteraction class]));
- });
-
- it(@"should not finish", ^{
- expect(hasCalledOperationCompletionHandler).toEventually(beFalse());
- expect(testCancelOp.isExecuting).toEventually(beTrue());
- expect(testCancelOp.isFinished).toEventually(beFalse());
- expect(testCancelOp.isCancelled).toEventually(beTrue());
- });
- });
-
- context(@"If the operation has not started", ^{
- beforeEach(^{
- expect(testCancelOp.isExecuting).to(beFalse());
- expect(testCancelOp.isFinished).to(beFalse());
- expect(testCancelOp.isCancelled).to(beFalse());
-
- [testChoiceSet cancel];
- });
-
- it(@"should not attempt to send a cancel interaction", ^{
- SDLCancelInteraction *lastRequest = testConnectionManager.receivedRequests.lastObject;
- expect(lastRequest).toNot(beAnInstanceOf([SDLCancelInteraction class]));
- });
-
- context(@"Once the operation has started", ^{
- beforeEach(^{
- [testCancelOp start];
- });
-
- it(@"should not attempt to send a cancel interaction", ^{
- SDLCancelInteraction *lastRequest = testConnectionManager.receivedRequests.lastObject;
- expect(lastRequest).toNot(beAnInstanceOf([SDLCancelInteraction class]));
- });
-
- it(@"should finish", ^{
- expect(hasCalledOperationCompletionHandler).toEventually(beTrue());
- expect(testCancelOp.isExecuting).toEventually(beFalse());
- expect(testCancelOp.isFinished).toEventually(beTrue());
- expect(testCancelOp.isCancelled).toEventually(beTrue());
- });
- });
- });
- });
-
- context(@"Head unit does not support the `CancelInteration` RPC", ^{
- beforeEach(^{
- SDLVersion *unsupportedVersion = [SDLVersion versionWithMajor:5 minor:1 patch:0];
- id globalMock = OCMPartialMock([SDLGlobals sharedGlobals]);
- OCMStub([globalMock rpcVersion]).andReturn(unsupportedVersion);
- });
-
- it(@"should not attempt to send a cancel interaction if the operation is executing", ^{
- [testCancelOp start];
-
- expect(testCancelOp.isExecuting).to(beTrue());
- expect(testCancelOp.isFinished).to(beFalse());
- expect(testCancelOp.isCancelled).to(beFalse());
-
- [testChoiceSet cancel];
-
- SDLCancelInteraction *lastRequest = testConnectionManager.receivedRequests.lastObject;
- expect(lastRequest).toNot(beAnInstanceOf([SDLCancelInteraction class]));
- });
-
- it(@"should cancel the operation if it has not yet been run", ^{
- expect(testCancelOp.isExecuting).to(beFalse());
- expect(testCancelOp.isFinished).to(beFalse());
- expect(testCancelOp.isCancelled).to(beFalse());
-
- [testChoiceSet cancel];
-
- SDLCancelInteraction *lastRequest = testConnectionManager.receivedRequests.lastObject;
- expect(lastRequest).toNot(beAnInstanceOf([SDLCancelInteraction class]));
-
- expect(testCancelOp.isExecuting).to(beFalse());
- expect(testCancelOp.isFinished).to(beFalse());
- expect(testCancelOp.isCancelled).to(beTrue());
- });
- });
- });
- });
-
- describe(@"running a searchable choice set operation", ^{
- beforeEach(^{
- testOp = [[SDLPresentChoiceSetOperation alloc] initWithConnectionManager:testConnectionManager choiceSet:testChoiceSet mode:testInteractionMode keyboardProperties:testKeyboardProperties keyboardDelegate:testKeyboardDelegate cancelID:testCancelID windowCapability:windowCapability];
-
- testOp.completionBlock = ^{
- hasCalledOperationCompletionHandler = YES;
- };
- [testOp start];
- });
-
- it(@"should ask for custom properties", ^{
- OCMVerify([testKeyboardDelegate customKeyboardConfiguration]);
- });
-
- it(@"should update global keyboard properties", ^{
- expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLSetGlobalProperties class]));
- });
-
- describe(@"presenting the keyboard", ^{
- beforeEach(^{
- SDLSetGlobalPropertiesResponse *response = [[SDLSetGlobalPropertiesResponse alloc] init];
- response.success = @YES;
- [testConnectionManager respondToLastRequestWithResponse:response];
- });
-
- it(@"should send the perform interaction", ^{
- expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLPerformInteraction class]));
- SDLPerformInteraction *request = testConnectionManager.receivedRequests.lastObject;
- expect(request.initialText).to(equal(testChoiceSet.title));
- expect(request.initialPrompt).to(equal(testChoiceSet.initialPrompt));
- expect(request.interactionMode).to(equal(testInteractionMode));
- expect(request.interactionLayout).to(equal(SDLLayoutModeIconWithSearch));
- expect(request.timeoutPrompt).to(equal(testChoiceSet.timeoutPrompt));
- expect(request.helpPrompt).to(equal(testChoiceSet.helpPrompt));
- expect(request.timeout).to(equal(testChoiceSet.timeout * 1000));
- expect(request.vrHelp).to(beNil());
- expect(request.interactionChoiceSetIDList).to(equal(@[@65535]));
- expect(request.cancelID).to(equal(testCancelID));
- });
-
- it(@"should respond to submitted notifications", ^{
- NSString *inputData = @"Test";
- SDLRPCNotificationNotification *notification = nil;
-
- // Submit notification
- SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
- input.event = SDLKeyboardEventSubmitted;
- input.data = inputData;
- notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
-
- [[NSNotificationCenter defaultCenter] postNotification:notification];
-
- OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventSubmitted];
- }] text:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(NSString *)obj isEqualToString:inputData];
- }]]);
-
- OCMVerify([testKeyboardDelegate userDidSubmitInput:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(NSString *)obj isEqualToString:inputData];
- }] withEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventSubmitted];
- }]]);
- });
-
- it(@"should respond to voice request notifications", ^{
- SDLRPCNotificationNotification *notification = nil;
-
- // Submit notification
- SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
- input.event = SDLKeyboardEventVoice;
- notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
-
- [[NSNotificationCenter defaultCenter] postNotification:notification];
-
- OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventVoice];
- }] text:[OCMArg isNil]]);
-
- OCMVerify([testKeyboardDelegate userDidSubmitInput:[OCMArg isNil] withEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventVoice];
- }]]);
- });
-
- it(@"should respond to abort notifications", ^{
- SDLRPCNotificationNotification *notification = nil;
-
- // Submit notification
- SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
- input.event = SDLKeyboardEventAborted;
- notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
-
- [[NSNotificationCenter defaultCenter] postNotification:notification];
-
- OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventAborted];
- }] text:[OCMArg isNil]]);
-
- OCMVerify([testKeyboardDelegate keyboardDidAbortWithReason:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventAborted];
- }]]);
- });
-
- it(@"should respond to enabled keyboard event", ^{
- SDLRPCNotificationNotification *notification = nil;
-
- // Submit notification
- SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
- input.event = SDLKeyboardEventInputKeyMaskEnabled;
- notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
-
- [[NSNotificationCenter defaultCenter] postNotification:notification];
-
- OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventInputKeyMaskEnabled];
- }] text:[OCMArg isNil]]);
-
- OCMVerify([testKeyboardDelegate keyboardDidUpdateInputMask:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventInputKeyMaskEnabled];
- }]]);
- });
-
- it(@"should respond to cancellation notifications", ^{
- SDLRPCNotificationNotification *notification = nil;
-
- // Submit notification
- SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
- input.event = SDLKeyboardEventCancelled;
- notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
-
- [[NSNotificationCenter defaultCenter] postNotification:notification];
-
- OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventCancelled];
- }] text:[OCMArg isNil]]);
-
- OCMVerify([testKeyboardDelegate keyboardDidAbortWithReason:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventCancelled];
- }]]);
- });
-
- it(@"should respond to text input notification with autocomplete", ^{
- NSString *inputData = @"Test";
- SDLRPCNotificationNotification *notification = nil;
-
- OCMStub([testKeyboardDelegate updateAutocompleteWithInput:[OCMArg any] autoCompleteResultsHandler:([OCMArg invokeBlockWithArgs:@[inputData], nil])]);
-
- // Submit notification
- SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
- input.event = SDLKeyboardEventKeypress;
- input.data = inputData;
- notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
-
- [[NSNotificationCenter defaultCenter] postNotification:notification];
-
- OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventKeypress];
- }] text:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(NSString *)obj isEqualToString:inputData];
- }]]);
-
- OCMVerify([testKeyboardDelegate updateAutocompleteWithInput:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(NSString *)obj isEqualToString:inputData];
- }] autoCompleteResultsHandler:[OCMArg any]]);
-
- expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLSetGlobalProperties class]));
-
- SDLSetGlobalProperties *setProperties = testConnectionManager.receivedRequests.lastObject;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- expect(setProperties.keyboardProperties.autoCompleteText).to(equal(inputData));
-#pragma clang diagnostic pop
- });
-
- it(@"should respond to text input notification with character set", ^{
- NSString *inputData = @"Test";
- SDLRPCNotificationNotification *notification = nil;
-
- OCMStub([testKeyboardDelegate updateCharacterSetWithInput:[OCMArg any] completionHandler:([OCMArg invokeBlockWithArgs:@[inputData], nil])]);
-
- // Submit notification
- SDLOnKeyboardInput *input = [[SDLOnKeyboardInput alloc] init];
- input.event = SDLKeyboardEventKeypress;
- input.data = inputData;
- notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveKeyboardInputNotification object:nil rpcNotification:input];
-
- [[NSNotificationCenter defaultCenter] postNotification:notification];
-
- OCMVerify([testKeyboardDelegate keyboardDidSendEvent:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(SDLKeyboardEvent)obj isEqualToEnum:SDLKeyboardEventKeypress];
- }] text:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(NSString *)obj isEqualToString:inputData];
- }]]);
-
- OCMVerify([testKeyboardDelegate updateCharacterSetWithInput:[OCMArg checkWithBlock:^BOOL(id obj) {
- return [(NSString *)obj isEqualToString:inputData];
- }] completionHandler:[OCMArg any]]);
-
- expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLSetGlobalProperties class]));
-
- SDLSetGlobalProperties *setProperties = testConnectionManager.receivedRequests.lastObject;
- expect(setProperties.keyboardProperties.limitedCharacterList).to(equal(@[inputData]));
- });
-
- describe(@"after a perform interaction response", ^{
- beforeEach(^{
- SDLPerformInteractionResponse *response = [[SDLPerformInteractionResponse alloc] init];
- response.success = @YES;
-
- [testConnectionManager respondToLastRequestWithResponse:response];
- });
-
- it(@"should reset the keyboard properties", ^{
- expect(testConnectionManager.receivedRequests.lastObject).to(beAnInstanceOf([SDLSetGlobalProperties class]));
- });
-
- describe(@"after the reset response", ^{
- beforeEach(^{
- SDLSetGlobalPropertiesResponse *response = [[SDLSetGlobalPropertiesResponse alloc] init];
- response.success = @YES;
- [testConnectionManager respondToLastRequestWithResponse:response];
- });
-
- it(@"should be finished", ^{
- expect(hasCalledOperationCompletionHandler).toEventually(beTrue());
- expect(testOp.isFinished).toEventually(beTrue());
- });
- });
- });
- });
- });
-});
-
-QuickSpecEnd