From b4913be6cd13cf5c2e7806a8963f4f2eefaa2325 Mon Sep 17 00:00:00 2001 From: michael starke Date: Mon, 10 Aug 2015 15:23:31 +0200 Subject: [PATCH] Splitted MacPass tests from KeePassKit tests Signed-off-by: michael starke --- MacPass.xcodeproj/project.pbxproj | 6 +- MacPassTests/KPKTestAutotype.m | 221 --------------------------- MacPassTests/MPTestAutotype.m | 239 ++++++++++++++++++++++++++++++ 3 files changed, 243 insertions(+), 223 deletions(-) create mode 100644 MacPassTests/MPTestAutotype.m diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj index b5700d77..2ca9db2d 100644 --- a/MacPass.xcodeproj/project.pbxproj +++ b/MacPass.xcodeproj/project.pbxproj @@ -23,6 +23,7 @@ 4C0DD6C618B2A44700FCB193 /* AutotypeCandidateSelectionWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C0DD6C518B2A44700FCB193 /* AutotypeCandidateSelectionWindow.xib */; }; 4C0F647817B6B65E00D9522A /* MPSheetWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0F647717B6B65E00D9522A /* MPSheetWindowController.m */; }; 4C0F647B17B6BC9C00D9522A /* MPSavePanelAccessoryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0F647A17B6BC9C00D9522A /* MPSavePanelAccessoryViewController.m */; }; + 4C10207F1B750E2F00BFCD59 /* MPTestAutotype.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C10207E1B750E2F00BFCD59 /* MPTestAutotype.m */; }; 4C10412C178CDD44001B5239 /* NSDate+Humanized.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C10412B178CDD44001B5239 /* NSDate+Humanized.m */; }; 4C15B74618BCA3B1003F8008 /* MPDocument+Search.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C15B74518BCA3B1003F8008 /* MPDocument+Search.m */; }; 4C17D8E517A1C780006C8C1E /* MPDocumentWindowDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C17D8E417A1C780006C8C1E /* MPDocumentWindowDelegate.m */; }; @@ -456,6 +457,7 @@ 4C0F647717B6B65E00D9522A /* MPSheetWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSheetWindowController.m; sourceTree = ""; }; 4C0F647917B6BC9C00D9522A /* MPSavePanelAccessoryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSavePanelAccessoryViewController.h; sourceTree = ""; }; 4C0F647A17B6BC9C00D9522A /* MPSavePanelAccessoryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSavePanelAccessoryViewController.m; sourceTree = ""; }; + 4C10207E1B750E2F00BFCD59 /* MPTestAutotype.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTestAutotype.m; sourceTree = ""; }; 4C10412A178CDD44001B5239 /* NSDate+Humanized.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+Humanized.h"; sourceTree = ""; }; 4C10412B178CDD44001B5239 /* NSDate+Humanized.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+Humanized.m"; sourceTree = ""; }; 4C13904C17ADD1A300A62934 /* KPKTreeCrypting.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KPKTreeCrypting.h; sourceTree = ""; }; @@ -1614,6 +1616,7 @@ 4C4B6E3C1B5E24870082EEF2 /* MacPass */ = { isa = PBXGroup; children = ( + 4C10207E1B750E2F00BFCD59 /* MPTestAutotype.m */, 4C45FB2C178E0BCB0010007D /* MPDatabaseLoading.m */, 4C45FB2F178E0CE20010007D /* MPTestDocument.m */, 4C19E502178E2871002F2CD0 /* MPDatabasePasswordAndKeyfile.m */, @@ -2550,6 +2553,7 @@ 4CE76DAD17B3AD010043B82B /* KPKHashedDataTest.m in Sources */, 4CEAF85B17BA9B44001307A6 /* KPKTestKeyfileParsing.m in Sources */, 4C3F25211A3B0C95007DD98B /* KPKTextXMLUtilities.m in Sources */, + 4C10207F1B750E2F00BFCD59 /* MPTestAutotype.m in Sources */, 4C59745118B3CE7200C8EBD1 /* KPKTestAutotype.m in Sources */, 4C6FDD2117BC4F4C004AEEC8 /* KPKTestPlaceholder.m in Sources */, 4CBA561617C2EA4900CE13D3 /* KPKTestXmlWriting.m in Sources */, @@ -3053,7 +3057,6 @@ CLANG_WARN_EMPTY_BODY = YES; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( - "\\\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\\\"", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); @@ -3076,7 +3079,6 @@ CLANG_WARN_EMPTY_BODY = YES; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( - "\\\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\\\"", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); diff --git a/MacPassTests/KPKTestAutotype.m b/MacPassTests/KPKTestAutotype.m index e1a7c614..1c10d6ec 100644 --- a/MacPassTests/KPKTestAutotype.m +++ b/MacPassTests/KPKTestAutotype.m @@ -7,41 +7,14 @@ // #import -#import #import "NSString+Commands.h" -#import "MPAutotypeCommand.h" -#import "MPAutotypeContext.h" -#import "MPAutotypePaste.h" -#import "MPAutotypeKeyPress.h" - -#import "MPKeyMapper.h" - -#import "KPKEntry.h" -#import "KPKAttribute.h" -#import "KPKAutotype.h" -#import "KPKWindowAssociation.h" @interface KPKTestAutotype : XCTestCase -@property (strong) KPKEntry *entry; @end @implementation KPKTestAutotype -- (void)setUp { - [super setUp]; - self.entry = [[KPKEntry alloc] init]; - self.entry.title = @"Title"; - self.entry.url = @"www.myurl.com"; - self.entry.username = @"Username"; - self.entry.password = @"Password"; -} - -- (void)tearDown { - self.entry = nil; - [super tearDown]; -} - - (void)testSimpleNormalization { NSString *normalized = [@"Whoo %{%}{^}{SHIFT}+ {SPACE}{ENTER}^V%V~T" normalizedAutotypeSequence]; XCTAssertTrue([normalized isEqualToString:@"Whoo{SPACE}{ALT}{%}{^}{SHIFT}{SHIFT}{SPACE}{SPACE}{ENTER}{CONTROL}V{ALT}V{ENTER}T"]); @@ -61,198 +34,4 @@ XCTAssertTrue([@"{}{}{}{}{}{ }ThisIsValid{}{STOP}" validateCommmand]); } -- (void)testCaseInsenstivieKeyPress { - /* Command 1 */ - MPAutotypeContext *context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:@"{TAB}{ENTER}~{tAb}{ShIfT}{enter}"]; - NSArray *commands = [MPAutotypeCommand commandsForContext:context]; - - XCTAssertTrue(commands.count == 5); - /* {TAB} */ - MPAutotypeKeyPress *keyPress = commands[0]; - XCTAssertEqual(keyPress.keyCode, kVK_Tab); - XCTAssertEqual(keyPress.modifierMask, 0); - - /* {ENTER} */ - keyPress = commands[1]; - XCTAssertEqual(keyPress.keyCode, kVK_Return); - XCTAssertEqual(keyPress.modifierMask, 0); - - /* ~ -> Enter */ - keyPress = commands[2]; - XCTAssertEqual(keyPress.keyCode, kVK_Return); - XCTAssertEqual(keyPress.modifierMask, 0); - - /* {tAb} */ - keyPress = commands[3]; - XCTAssertEqual(keyPress.keyCode, kVK_Tab); - XCTAssertEqual(keyPress.modifierMask, 0); - - /* {ShIfT}{enter}*/ - keyPress = commands[4]; - XCTAssertEqual(keyPress.keyCode, kVK_Return); - XCTAssertEqual(keyPress.modifierMask, kCGEventFlagMaskShift); -} - -- (void)testCaseSensitiveCustomAttributeLookup { - KPKAttribute *lowerCaseAttribute = [[KPKAttribute alloc] initWithKey:@"custom" value:@"value"]; - KPKAttribute *upperCaseAttribute = [[KPKAttribute alloc] initWithKey:@"CUSTOM" value:@"VALUE"]; - KPKAttribute *mixedCaseAttribute = [[KPKAttribute alloc] initWithKey:@"CuStOm" value:@"VaLuE"]; - KPKAttribute *randomCase = [[KPKAttribute alloc] initWithKey:@"custoM" value:@"valuE"]; - [self.entry addCustomAttribute:lowerCaseAttribute]; - [self.entry addCustomAttribute:upperCaseAttribute]; - [self.entry addCustomAttribute:mixedCaseAttribute]; - [self.entry addCustomAttribute:randomCase]; - - self.entry.autotype.defaultKeystrokeSequence = [[NSString alloc] initWithFormat:@"{USERNAME}{s:%@}{S:%@}{s:%@}", lowerCaseAttribute.key, mixedCaseAttribute.key, upperCaseAttribute.key]; - - MPAutotypeContext *context = [[MPAutotypeContext alloc] initWithDefaultSequenceForEntry:self.entry]; - NSString *result = [[NSString alloc] initWithFormat:@"%@%@%@%@", self.entry.username, lowerCaseAttribute.value, mixedCaseAttribute.value, upperCaseAttribute.value]; - XCTAssertTrue([[context evaluatedCommand] isEqualToString:result]); -} - -- (void)testCustomAttributeRepetition { - KPKAttribute *numberAttribute = [[KPKAttribute alloc] initWithKey:@"NoRepeat 3" value:@"NoRepeatValue"]; - [self.entry addCustomAttribute:numberAttribute]; - - NSString *autotypeSequence = [[NSString alloc] initWithFormat:@"{S:%@}{USERNAME 3}", numberAttribute.key]; - MPAutotypeContext *context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:autotypeSequence]; - - NSArray *commands = [MPAutotypeCommand commandsForContext:context]; - XCTAssertEqual(commands.count, 1); - MPAutotypePaste *paste = commands[0]; - NSString *result = [[NSString alloc] initWithFormat:@"%@%@%@%@", numberAttribute.value, self.entry.username, self.entry.username, self.entry.username]; - XCTAssertEqualObjects(paste.pasteData, result); -} - -- (void)testFunctionKeyCommand { - MPAutotypeContext *context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:@"{F0}{F1}{F2}{F3}{F4}{F5}^%{F6}{F7}{F19}{F20}"]; - NSArray *commands = [MPAutotypeCommand commandsForContext:context]; - XCTAssertEqual(commands.count, 10); - /* {F0} -> invalid, paste */ - MPAutotypePaste *paste = commands[0]; - XCTAssertEqualObjects(paste.pasteData, @"{F0}"); - - /* {F1} */ - MPAutotypeKeyPress *key = commands[1]; - XCTAssertEqual(key.modifierMask, 0); - XCTAssertEqual(key.keyCode, kVK_F1); - - /* {F2} */ - key = commands[2]; - XCTAssertEqual(key.modifierMask, 0); - XCTAssertEqual(key.keyCode, kVK_F2); - - /* {F3} */ - key = commands[3]; - XCTAssertEqual(key.modifierMask, 0); - XCTAssertEqual(key.keyCode, kVK_F3); - - /* {F4} */ - key = commands[4]; - XCTAssertEqual(key.modifierMask, 0); - XCTAssertEqual(key.keyCode, kVK_F4); - - /* {F5} */ - key = commands[5]; - XCTAssertEqual(key.modifierMask, 0); - XCTAssertEqual(key.keyCode, kVK_F5); - - /* ^%{F6} */ - key = commands[6]; - XCTAssertEqual(key.modifierMask, (kCGEventFlagMaskCommand | kCGEventFlagMaskAlternate)); - XCTAssertEqual(key.keyCode, kVK_F6); - - /* {F7} */ - key = commands[7]; - XCTAssertEqual(key.modifierMask, 0); - XCTAssertEqual(key.keyCode, kVK_F7); - - /* {F19} */ - key = commands[8]; - XCTAssertEqual(key.modifierMask, 0); - XCTAssertEqual(key.keyCode, kVK_F19); - - paste = commands[9]; - XCTAssertEqualObjects(paste.pasteData, @"{F20}"); -} - -- (void)testCommandCreation { - /* Command 1 */ - MPAutotypeContext *context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:@"{USERNAME}{TAB}{PASSWORD}{ENTER}"]; - NSArray *commands = [MPAutotypeCommand commandsForContext:context]; - - XCTAssertTrue(commands.count == 4); - XCTAssertTrue([commands[0] isKindOfClass:[MPAutotypePaste class]]); - XCTAssertTrue([commands[1] isKindOfClass:[MPAutotypeKeyPress class]]); - XCTAssertTrue([commands[2] isKindOfClass:[MPAutotypePaste class]]); - XCTAssertTrue([commands[3] isKindOfClass:[MPAutotypeKeyPress class]]); - - /* {USERNAME} */ - MPAutotypePaste *paste = commands[0]; - XCTAssertTrue([paste.pasteData isEqualToString:self.entry.username]); - - /* {TAB} */ - MPAutotypeKeyPress *keyPress = commands[1]; - XCTAssertEqual(keyPress.keyCode, kVK_Tab); // Tab is a fixed key, no mapping needed - XCTAssertEqual(keyPress.modifierMask, 0); - - /* {PASSWORD} */ - paste = commands[2]; - XCTAssertTrue([self.entry.password isEqualToString:paste.pasteData]); - - /* {ENTER} */ - keyPress = commands[3]; - XCTAssertEqual(keyPress.keyCode, kVK_Return); - - /* Command 2 */ - context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:@"^T{USERNAME}%+^{TAB}Whoo{PASSWORD}{ENTER}"]; - commands = [MPAutotypeCommand commandsForContext:context]; - XCTAssertTrue(commands.count == 5); - XCTAssertTrue([commands[0] isKindOfClass:[MPAutotypeKeyPress class]]); - XCTAssertTrue([commands[1] isKindOfClass:[MPAutotypePaste class]]); - XCTAssertTrue([commands[2] isKindOfClass:[MPAutotypeKeyPress class]]); - XCTAssertTrue([commands[3] isKindOfClass:[MPAutotypePaste class]]); - XCTAssertTrue([commands[4] isKindOfClass:[MPAutotypeKeyPress class]]); - - /* ^T */ - keyPress = commands[0]; - /* Lower case is ok, since we only need the key, not the sequence to reproduce the string */ - XCTAssertTrue([@"t" isEqualToString:[MPKeyMapper stringForKey:keyPress.keyCode]]); - XCTAssertEqual(keyPress.modifierMask, kCGEventFlagMaskCommand); - - /* {USERNAME} */ - paste = commands[1]; - XCTAssertTrue([paste.pasteData isEqualToString:self.entry.username]); - - /* %+^{TAB} */ - keyPress = commands[2]; - XCTAssertEqual(keyPress.keyCode, kVK_Tab); // Tab is a fixed key, no mapping needed - XCTAssertEqual(keyPress.modifierMask, (kCGEventFlagMaskCommand | kCGEventFlagMaskShift | kCGEventFlagMaskAlternate)); - - /* Whoo{PASSWORD} */ - paste = commands[3]; - NSString *pasteString = [[NSString alloc] initWithFormat:@"%@%@", @"Whoo", self.entry.password]; - XCTAssertTrue([pasteString isEqualToString:paste.pasteData]); - - /* {ENTER} */ - keyPress = commands[4]; - XCTAssertEqual(keyPress.keyCode, kVK_Return); - XCTAssertEqual(keyPress.modifierMask, 0); - - - /* Command 3 */ - context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:@"^T"]; - commands = [MPAutotypeCommand commandsForContext:context]; - XCTAssertTrue(commands.count == 1); - XCTAssertTrue([commands[0] isKindOfClass:[MPAutotypeKeyPress class]]); - - /*^T*/ - keyPress = commands[0]; - XCTAssertEqualObjects(@"t", [MPKeyMapper stringForKey:keyPress.keyCode]); - /* TODO - Respect user settings? */ - XCTAssertEqual(keyPress.modifierMask, kCGEventFlagMaskCommand); - /*XCTAssertEqual(keyPress.modifierMask, kCGEventFlagMaskControl);*/ - - -} @end diff --git a/MacPassTests/MPTestAutotype.m b/MacPassTests/MPTestAutotype.m new file mode 100644 index 00000000..9cf1b9c9 --- /dev/null +++ b/MacPassTests/MPTestAutotype.m @@ -0,0 +1,239 @@ +// +// MPTestAutotype.m +// MacPass +// +// Created by Michael Starke on 07/08/15. +// Copyright (c) 2015 HicknHack Software GmbH. All rights reserved. +// + +#import +#import +#import + +#import "MPAutotypeCommand.h" +#import "MPAutotypeContext.h" +#import "MPAutotypePaste.h" +#import "MPAutotypeKeyPress.h" + +#import "MPKeyMapper.h" + +#import "KPKEntry.h" +#import "KPKAttribute.h" +#import "KPKAutotype.h" +#import "KPKWindowAssociation.h" + +@interface MPTestAutotype : XCTestCase +@property (strong) KPKEntry *entry; +@end + +@implementation MPTestAutotype + +- (void)setUp { + [super setUp]; + self.entry = [[KPKEntry alloc] init]; + self.entry.title = @"Title"; + self.entry.url = @"www.myurl.com"; + self.entry.username = @"Username"; + self.entry.password = @"Password"; +} + +- (void)tearDown { + self.entry = nil; + [super tearDown]; +} + +- (void)testCaseInsenstivieKeyPress { + /* Command 1 */ + MPAutotypeContext *context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:@"{TAB}{ENTER}~{tAb}{ShIfT}{enter}"]; + NSArray *commands = [MPAutotypeCommand commandsForContext:context]; + + XCTAssertTrue(commands.count == 5); + /* {TAB} */ + MPAutotypeKeyPress *keyPress = commands[0]; + XCTAssertEqual(keyPress.keyCode, kVK_Tab); + XCTAssertEqual(keyPress.modifierMask, 0); + + /* {ENTER} */ + keyPress = commands[1]; + XCTAssertEqual(keyPress.keyCode, kVK_Return); + XCTAssertEqual(keyPress.modifierMask, 0); + + /* ~ -> Enter */ + keyPress = commands[2]; + XCTAssertEqual(keyPress.keyCode, kVK_Return); + XCTAssertEqual(keyPress.modifierMask, 0); + + /* {tAb} */ + keyPress = commands[3]; + XCTAssertEqual(keyPress.keyCode, kVK_Tab); + XCTAssertEqual(keyPress.modifierMask, 0); + + /* {ShIfT}{enter}*/ + keyPress = commands[4]; + XCTAssertEqual(keyPress.keyCode, kVK_Return); + XCTAssertEqual(keyPress.modifierMask, kCGEventFlagMaskShift); +} + +- (void)testCaseSensitiveCustomAttributeLookup { + KPKAttribute *lowerCaseAttribute = [[KPKAttribute alloc] initWithKey:@"custom" value:@"value"]; + KPKAttribute *upperCaseAttribute = [[KPKAttribute alloc] initWithKey:@"CUSTOM" value:@"VALUE"]; + KPKAttribute *mixedCaseAttribute = [[KPKAttribute alloc] initWithKey:@"CuStOm" value:@"VaLuE"]; + KPKAttribute *randomCase = [[KPKAttribute alloc] initWithKey:@"custoM" value:@"valuE"]; + [self.entry addCustomAttribute:lowerCaseAttribute]; + [self.entry addCustomAttribute:upperCaseAttribute]; + [self.entry addCustomAttribute:mixedCaseAttribute]; + [self.entry addCustomAttribute:randomCase]; + + self.entry.autotype.defaultKeystrokeSequence = [[NSString alloc] initWithFormat:@"{USERNAME}{s:%@}{S:%@}{s:%@}", lowerCaseAttribute.key, mixedCaseAttribute.key, upperCaseAttribute.key]; + + MPAutotypeContext *context = [[MPAutotypeContext alloc] initWithDefaultSequenceForEntry:self.entry]; + NSString *result = [[NSString alloc] initWithFormat:@"%@%@%@%@", self.entry.username, lowerCaseAttribute.value, mixedCaseAttribute.value, upperCaseAttribute.value]; + XCTAssertTrue([[context evaluatedCommand] isEqualToString:result]); +} + +- (void)testCustomAttributeRepetition { + KPKAttribute *numberAttribute = [[KPKAttribute alloc] initWithKey:@"NoRepeat 3" value:@"NoRepeatValue"]; + [self.entry addCustomAttribute:numberAttribute]; + + NSString *autotypeSequence = [[NSString alloc] initWithFormat:@"{S:%@}{USERNAME 3}", numberAttribute.key]; + MPAutotypeContext *context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:autotypeSequence]; + + NSArray *commands = [MPAutotypeCommand commandsForContext:context]; + XCTAssertEqual(commands.count, 1); + MPAutotypePaste *paste = commands[0]; + NSString *result = [[NSString alloc] initWithFormat:@"%@%@%@%@", numberAttribute.value, self.entry.username, self.entry.username, self.entry.username]; + XCTAssertEqualObjects(paste.pasteData, result); +} + +- (void)testFunctionKeyCommand { + MPAutotypeContext *context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:@"{F0}{F1}{F2}{F3}{F4}{F5}^%{F6}{F7}{F19}{F20}"]; + NSArray *commands = [MPAutotypeCommand commandsForContext:context]; + XCTAssertEqual(commands.count, 10); + /* {F0} -> invalid, paste */ + MPAutotypePaste *paste = commands[0]; + XCTAssertEqualObjects(paste.pasteData, @"{F0}"); + + /* {F1} */ + MPAutotypeKeyPress *key = commands[1]; + XCTAssertEqual(key.modifierMask, 0); + XCTAssertEqual(key.keyCode, kVK_F1); + + /* {F2} */ + key = commands[2]; + XCTAssertEqual(key.modifierMask, 0); + XCTAssertEqual(key.keyCode, kVK_F2); + + /* {F3} */ + key = commands[3]; + XCTAssertEqual(key.modifierMask, 0); + XCTAssertEqual(key.keyCode, kVK_F3); + + /* {F4} */ + key = commands[4]; + XCTAssertEqual(key.modifierMask, 0); + XCTAssertEqual(key.keyCode, kVK_F4); + + /* {F5} */ + key = commands[5]; + XCTAssertEqual(key.modifierMask, 0); + XCTAssertEqual(key.keyCode, kVK_F5); + + /* ^%{F6} */ + key = commands[6]; + XCTAssertEqual(key.modifierMask, (kCGEventFlagMaskCommand | kCGEventFlagMaskAlternate)); + XCTAssertEqual(key.keyCode, kVK_F6); + + /* {F7} */ + key = commands[7]; + XCTAssertEqual(key.modifierMask, 0); + XCTAssertEqual(key.keyCode, kVK_F7); + + /* {F19} */ + key = commands[8]; + XCTAssertEqual(key.modifierMask, 0); + XCTAssertEqual(key.keyCode, kVK_F19); + + paste = commands[9]; + XCTAssertEqualObjects(paste.pasteData, @"{F20}"); +} + +- (void)testCommandCreation { + /* Command 1 */ + MPAutotypeContext *context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:@"{USERNAME}{TAB}{PASSWORD}{ENTER}"]; + NSArray *commands = [MPAutotypeCommand commandsForContext:context]; + + XCTAssertTrue(commands.count == 4); + XCTAssertTrue([commands[0] isKindOfClass:[MPAutotypePaste class]]); + XCTAssertTrue([commands[1] isKindOfClass:[MPAutotypeKeyPress class]]); + XCTAssertTrue([commands[2] isKindOfClass:[MPAutotypePaste class]]); + XCTAssertTrue([commands[3] isKindOfClass:[MPAutotypeKeyPress class]]); + + /* {USERNAME} */ + MPAutotypePaste *paste = commands[0]; + XCTAssertTrue([paste.pasteData isEqualToString:self.entry.username]); + + /* {TAB} */ + MPAutotypeKeyPress *keyPress = commands[1]; + XCTAssertEqual(keyPress.keyCode, kVK_Tab); // Tab is a fixed key, no mapping needed + XCTAssertEqual(keyPress.modifierMask, 0); + + /* {PASSWORD} */ + paste = commands[2]; + XCTAssertTrue([self.entry.password isEqualToString:paste.pasteData]); + + /* {ENTER} */ + keyPress = commands[3]; + XCTAssertEqual(keyPress.keyCode, kVK_Return); + + /* Command 2 */ + context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:@"^T{USERNAME}%+^{TAB}Whoo{PASSWORD}{ENTER}"]; + commands = [MPAutotypeCommand commandsForContext:context]; + XCTAssertTrue(commands.count == 5); + XCTAssertTrue([commands[0] isKindOfClass:[MPAutotypeKeyPress class]]); + XCTAssertTrue([commands[1] isKindOfClass:[MPAutotypePaste class]]); + XCTAssertTrue([commands[2] isKindOfClass:[MPAutotypeKeyPress class]]); + XCTAssertTrue([commands[3] isKindOfClass:[MPAutotypePaste class]]); + XCTAssertTrue([commands[4] isKindOfClass:[MPAutotypeKeyPress class]]); + + /* ^T */ + keyPress = commands[0]; + /* Lower case is ok, since we only need the key, not the sequence to reproduce the string */ + XCTAssertTrue([@"t" isEqualToString:[MPKeyMapper stringForKey:keyPress.keyCode]]); + XCTAssertEqual(keyPress.modifierMask, kCGEventFlagMaskCommand); + + /* {USERNAME} */ + paste = commands[1]; + XCTAssertTrue([paste.pasteData isEqualToString:self.entry.username]); + + /* %+^{TAB} */ + keyPress = commands[2]; + XCTAssertEqual(keyPress.keyCode, kVK_Tab); // Tab is a fixed key, no mapping needed + XCTAssertEqual(keyPress.modifierMask, (kCGEventFlagMaskCommand | kCGEventFlagMaskShift | kCGEventFlagMaskAlternate)); + + /* Whoo{PASSWORD} */ + paste = commands[3]; + NSString *pasteString = [[NSString alloc] initWithFormat:@"%@%@", @"Whoo", self.entry.password]; + XCTAssertTrue([pasteString isEqualToString:paste.pasteData]); + + /* {ENTER} */ + keyPress = commands[4]; + XCTAssertEqual(keyPress.keyCode, kVK_Return); + XCTAssertEqual(keyPress.modifierMask, 0); + + + /* Command 3 */ + context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:@"^T"]; + commands = [MPAutotypeCommand commandsForContext:context]; + XCTAssertTrue(commands.count == 1); + XCTAssertTrue([commands[0] isKindOfClass:[MPAutotypeKeyPress class]]); + + /*^T*/ + keyPress = commands[0]; + XCTAssertEqualObjects(@"t", [MPKeyMapper stringForKey:keyPress.keyCode]); + /* TODO - Respect user settings? */ + XCTAssertEqual(keyPress.modifierMask, kCGEventFlagMaskCommand); + /*XCTAssertEqual(keyPress.modifierMask, kCGEventFlagMaskControl);*/ + +} + +@end