Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix: Pass-through modifier keys #918

Merged
merged 4 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 4 additions & 9 deletions WebDriverAgentLib/Utilities/FBW3CActionsHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,14 @@ NSString *_Nullable FBRequireValue(NSDictionary<NSString *, id> *actionItem, NSE
*/
NSNumber *_Nullable FBOptDuration(NSDictionary<NSString *, id> *actionItem, NSNumber *_Nullable defaultValue, NSError **error);

/**
* Checks whether the given key action value is a W3C meta modifier
* @param value key action value
* @returns YES if the value is a meta modifier
*/
BOOL FBIsMetaModifier(NSString *value);

/**
* Maps W3C meta modifier to XCUITest compatible-one
* See https://w3c.github.io/webdriver/#keyboard-actions
*
* @param value key action value
* @returns the mapped modifier value or 0 in case of failure
* @returns the mapped modifier value or the same input character
* if no mapped value could be found for it.
*/
NSUInteger FBToMetaModifier(NSString *value);
NSString * FBMapIfSpecialCharacter(NSString *value);

NS_ASSUME_NONNULL_END
76 changes: 56 additions & 20 deletions WebDriverAgentLib/Utilities/FBW3CActionsHelpers.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,32 +53,68 @@
return durationObj;
}

BOOL FBIsMetaModifier(NSString *value)
NSString *FBMapIfSpecialCharacter(NSString *value)
{
unichar charCode = [value characterAtIndex:0];
return charCode >= 0xE000 && charCode <= 0xF8FF;
}

NSUInteger FBToMetaModifier(NSString *value)
{
if (!FBIsMetaModifier(value)) {
return 0;
if (0 == [value length]) {
return value;
}

unichar charCode = [value characterAtIndex:0];
switch (charCode) {
case 0xE000:
return XCUIKeyModifierNone;
case 0xE03D:
return XCUIKeyModifierCommand;
case 0xE009:
return XCUIKeyModifierControl;
case 0xE00A:
return XCUIKeyModifierOption;
case 0xE008:
return XCUIKeyModifierShift;
return @"";
case 0xE003:
return [NSString stringWithFormat:@"%C", 0x0008];
case 0xE004:
return [NSString stringWithFormat:@"%C", 0x0009];
case 0xE006:
return [NSString stringWithFormat:@"%C", 0x000D];
case 0xE007:
return [NSString stringWithFormat:@"%C", 0x000A];
case 0xE00C:
return [NSString stringWithFormat:@"%C", 0x001B];
case 0xE00D:
case 0xE05D:
return @" ";
case 0xE017:
return [NSString stringWithFormat:@"%C", 0x007F];
case 0xE018:
return @";";
case 0xE019:
return @"=";
case 0xE01A:
return @"0";
case 0xE01B:
return @"1";
case 0xE01C:
return @"2";
case 0xE01D:
return @"3";
case 0xE01E:
return @"4";
case 0xE01F:
return @"5";
case 0xE020:
return @"6";
case 0xE021:
return @"7";
case 0xE022:
return @"8";
case 0xE023:
return @"9";
case 0xE024:
return @"*";
case 0xE025:
return @"+";
case 0xE026:
return @",";
case 0xE027:
return @"-";
case 0xE028:
return @".";
case 0xE029:
return @"/";
default:
[FBLogger logFmt:@"Skipping the unsupported meta modifier with code %@", @(charCode)];
return 0;
return charCode >= 0xE000 && charCode <= 0xE05D ? @"" : value;
}
}
54 changes: 3 additions & 51 deletions WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m
Original file line number Diff line number Diff line change
Expand Up @@ -410,17 +410,12 @@ - (BOOL)hasDownPairInItems:(NSArray *)allItems
currentItemIndex:(NSUInteger)currentItemIndex
{
NSInteger balance = 1;
BOOL isSelfMetaModifier = FBIsMetaModifier(self.value);
for (NSInteger index = currentItemIndex - 1; index >= 0; index--) {
FBW3CKeyItem *item = [allItems objectAtIndex:index];
BOOL isKeyDown = [item isKindOfClass:FBKeyDownItem.class];
BOOL isKeyUp = !isKeyDown && [item isKindOfClass:FBKeyUpItem.class];
if (!isKeyUp && !isKeyDown) {
if (isSelfMetaModifier) {
continue;
} else {
break;
}
break;
}

NSString *value = [item performSelector:@selector(value)];
Expand All @@ -434,32 +429,6 @@ - (BOOL)hasDownPairInItems:(NSArray *)allItems
return 0 == balance;
}

- (NSUInteger)collectModifersWithItems:(NSArray *)allItems
currentItemIndex:(NSUInteger)currentItemIndex
{
NSUInteger modifiers = 0;
for (NSUInteger index = 0; index < currentItemIndex; index++) {
FBW3CKeyItem *item = [allItems objectAtIndex:index];
BOOL isKeyDown = [item isKindOfClass:FBKeyDownItem.class];
BOOL isKeyUp = !isKeyDown && [item isKindOfClass:FBKeyUpItem.class];
if (!isKeyUp && !isKeyDown) {
continue;
}

NSString *value = [item performSelector:@selector(value)];
NSUInteger modifier = FBToMetaModifier(value);
if (modifier > 0) {
if (isKeyDown) {
modifiers |= modifier;
} else if (item.offset < self.offset) {
// only cancel the modifier if it is not in the same group
modifiers &= ~modifier;
}
}
}
return modifiers;
}

- (NSString *)collectTextWithItems:(NSArray *)allItems
currentItemIndex:(NSUInteger)currentItemIndex
{
Expand All @@ -473,12 +442,8 @@ - (NSString *)collectTextWithItems:(NSArray *)allItems
}

NSString *value = [item performSelector:@selector(value)];
if (FBIsMetaModifier(value)) {
continue;
}

if (isKeyUp) {
[result addObject:value];
[result addObject:FBMapIfSpecialCharacter(value)];
}
}
return [result.reverseObjectEnumerator.allObjects componentsJoinedByString:@""];
Expand All @@ -497,10 +462,6 @@ - (NSString *)collectTextWithItems:(NSArray *)allItems
return nil;
}

if (FBIsMetaModifier(self.value)) {
return @[];
}

BOOL isLastKeyUpInGroup = currentItemIndex == allItems.count - 1
|| [[allItems objectAtIndex:currentItemIndex + 1] isKindOfClass:FBKeyPauseItem.class];
if (!isLastKeyUpInGroup) {
Expand All @@ -510,10 +471,6 @@ - (NSString *)collectTextWithItems:(NSArray *)allItems
NSString *text = [self collectTextWithItems:allItems currentItemIndex:currentItemIndex];
NSTimeInterval offset = FBMillisToSeconds(self.offset);
XCPointerEventPath *resultPath = [[XCPointerEventPath alloc] initForTextInput];
// TODO: Figure out how meta modifiers could be applied
// TODO: The current approach throws zero division error on execution
// NSUInteger modifiers = [self collectModifersWithItems:allItems currentItemIndex:currentItemIndex];
// [resultPath setModifiers:modifiers mergeWithCurrentModifierFlags:NO atOffset:0];
[resultPath typeText:text
atOffset:offset
typingSpeed:FBConfiguration.maxTypingFrequency
Expand Down Expand Up @@ -555,17 +512,12 @@ - (BOOL)hasUpPairInItems:(NSArray *)allItems
currentItemIndex:(NSUInteger)currentItemIndex
{
NSInteger balance = 1;
BOOL isSelfMetaModifier = FBIsMetaModifier(self.value);
for (NSUInteger index = currentItemIndex + 1; index < allItems.count; index++) {
FBW3CKeyItem *item = [allItems objectAtIndex:index];
BOOL isKeyDown = [item isKindOfClass:FBKeyDownItem.class];
BOOL isKeyUp = !isKeyDown && [item isKindOfClass:FBKeyUpItem.class];
if (!isKeyUp && !isKeyDown) {
if (isSelfMetaModifier) {
continue;
} else {
break;
}
break;
}

NSString *value = [item performSelector:@selector(value)];
Expand Down
8 changes: 6 additions & 2 deletions WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,22 @@ - (void)testTextTyping
@{@"type": @"keyUp", @"value": @"N"},
@{@"type": @"keyDown", @"value": @"B"},
@{@"type": @"keyUp", @"value": @"B"},
@{@"type": @"keyDown", @"value": @"A"},
@{@"type": @"keyUp", @"value": @"A"},
@{@"type": @"keyDown", @"value": @"a"},
@{@"type": @"keyUp", @"value": @"a"},
@{@"type": @"keyDown", @"value": [NSString stringWithFormat:@"%C", 0xE003]},
@{@"type": @"keyUp", @"value": [NSString stringWithFormat:@"%C", 0xE003]},
@{@"type": @"pause", @"duration": @500},
],
},
];
];
NSError *error;
XCTAssertTrue([self.testedApplication fb_performW3CActions:typeAction
elementCache:nil
error:&error]);
XCTAssertNil(error);
XCTAssertEqualObjects(textField.wdValue, @"🏀NBa");
XCTAssertEqualObjects(textField.wdValue, @"🏀NBA");
}

@end
Loading