appium-webdriveragent 8.7.6 → 8.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/WebDriverAgentLib/Info.plist +2 -2
- package/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.h +4 -9
- package/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.m +56 -20
- package/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +16 -67
- package/WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m +30 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## [8.7.8](https://github.com/appium/WebDriverAgent/compare/v8.7.7...v8.7.8) (2024-07-18)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* do nothing for an empty array in w3c actions ([#919](https://github.com/appium/WebDriverAgent/issues/919)) ([9e70ec1](https://github.com/appium/WebDriverAgent/commit/9e70ec1dbec1d1844278a58297a5b956ebaeb7fc))
|
|
6
|
+
|
|
7
|
+
## [8.7.7](https://github.com/appium/WebDriverAgent/compare/v8.7.6...v8.7.7) (2024-07-18)
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* Pass-through modifier keys ([#918](https://github.com/appium/WebDriverAgent/issues/918)) ([29d0e5c](https://github.com/appium/WebDriverAgent/commit/29d0e5cb2a19809e1babb06e5adaa49b43c754a5))
|
|
12
|
+
|
|
1
13
|
## [8.7.6](https://github.com/appium/WebDriverAgent/compare/v8.7.5...v8.7.6) (2024-07-02)
|
|
2
14
|
|
|
3
15
|
### Miscellaneous Chores
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
<key>CFBundlePackageType</key>
|
|
16
16
|
<string>FMWK</string>
|
|
17
17
|
<key>CFBundleShortVersionString</key>
|
|
18
|
-
<string>8.7.
|
|
18
|
+
<string>8.7.8</string>
|
|
19
19
|
<key>CFBundleSignature</key>
|
|
20
20
|
<string>????</string>
|
|
21
21
|
<key>CFBundleVersion</key>
|
|
22
|
-
<string>8.7.
|
|
22
|
+
<string>8.7.8</string>
|
|
23
23
|
<key>NSPrincipalClass</key>
|
|
24
24
|
<string/>
|
|
25
25
|
</dict>
|
|
@@ -30,19 +30,14 @@ NSString *_Nullable FBRequireValue(NSDictionary<NSString *, id> *actionItem, NSE
|
|
|
30
30
|
*/
|
|
31
31
|
NSNumber *_Nullable FBOptDuration(NSDictionary<NSString *, id> *actionItem, NSNumber *_Nullable defaultValue, NSError **error);
|
|
32
32
|
|
|
33
|
-
/**
|
|
34
|
-
* Checks whether the given key action value is a W3C meta modifier
|
|
35
|
-
* @param value key action value
|
|
36
|
-
* @returns YES if the value is a meta modifier
|
|
37
|
-
*/
|
|
38
|
-
BOOL FBIsMetaModifier(NSString *value);
|
|
39
|
-
|
|
40
33
|
/**
|
|
41
34
|
* Maps W3C meta modifier to XCUITest compatible-one
|
|
35
|
+
* See https://w3c.github.io/webdriver/#keyboard-actions
|
|
42
36
|
*
|
|
43
37
|
* @param value key action value
|
|
44
|
-
* @returns the mapped modifier value or
|
|
38
|
+
* @returns the mapped modifier value or the same input character
|
|
39
|
+
* if no mapped value could be found for it.
|
|
45
40
|
*/
|
|
46
|
-
|
|
41
|
+
NSString * FBMapIfSpecialCharacter(NSString *value);
|
|
47
42
|
|
|
48
43
|
NS_ASSUME_NONNULL_END
|
|
@@ -53,32 +53,68 @@ NSNumber *_Nullable FBOptDuration(NSDictionary<NSString *, id> *actionItem, NSNu
|
|
|
53
53
|
return durationObj;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
NSString *FBMapIfSpecialCharacter(NSString *value)
|
|
57
57
|
{
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
NSUInteger FBToMetaModifier(NSString *value)
|
|
63
|
-
{
|
|
64
|
-
if (!FBIsMetaModifier(value)) {
|
|
65
|
-
return 0;
|
|
58
|
+
if (0 == [value length]) {
|
|
59
|
+
return value;
|
|
66
60
|
}
|
|
67
61
|
|
|
68
62
|
unichar charCode = [value characterAtIndex:0];
|
|
69
63
|
switch (charCode) {
|
|
70
64
|
case 0xE000:
|
|
71
|
-
return
|
|
72
|
-
case
|
|
73
|
-
return
|
|
74
|
-
case
|
|
75
|
-
return
|
|
76
|
-
case
|
|
77
|
-
return
|
|
78
|
-
case
|
|
79
|
-
return
|
|
65
|
+
return @"";
|
|
66
|
+
case 0xE003:
|
|
67
|
+
return [NSString stringWithFormat:@"%C", 0x0008];
|
|
68
|
+
case 0xE004:
|
|
69
|
+
return [NSString stringWithFormat:@"%C", 0x0009];
|
|
70
|
+
case 0xE006:
|
|
71
|
+
return [NSString stringWithFormat:@"%C", 0x000D];
|
|
72
|
+
case 0xE007:
|
|
73
|
+
return [NSString stringWithFormat:@"%C", 0x000A];
|
|
74
|
+
case 0xE00C:
|
|
75
|
+
return [NSString stringWithFormat:@"%C", 0x001B];
|
|
76
|
+
case 0xE00D:
|
|
77
|
+
case 0xE05D:
|
|
78
|
+
return @" ";
|
|
79
|
+
case 0xE017:
|
|
80
|
+
return [NSString stringWithFormat:@"%C", 0x007F];
|
|
81
|
+
case 0xE018:
|
|
82
|
+
return @";";
|
|
83
|
+
case 0xE019:
|
|
84
|
+
return @"=";
|
|
85
|
+
case 0xE01A:
|
|
86
|
+
return @"0";
|
|
87
|
+
case 0xE01B:
|
|
88
|
+
return @"1";
|
|
89
|
+
case 0xE01C:
|
|
90
|
+
return @"2";
|
|
91
|
+
case 0xE01D:
|
|
92
|
+
return @"3";
|
|
93
|
+
case 0xE01E:
|
|
94
|
+
return @"4";
|
|
95
|
+
case 0xE01F:
|
|
96
|
+
return @"5";
|
|
97
|
+
case 0xE020:
|
|
98
|
+
return @"6";
|
|
99
|
+
case 0xE021:
|
|
100
|
+
return @"7";
|
|
101
|
+
case 0xE022:
|
|
102
|
+
return @"8";
|
|
103
|
+
case 0xE023:
|
|
104
|
+
return @"9";
|
|
105
|
+
case 0xE024:
|
|
106
|
+
return @"*";
|
|
107
|
+
case 0xE025:
|
|
108
|
+
return @"+";
|
|
109
|
+
case 0xE026:
|
|
110
|
+
return @",";
|
|
111
|
+
case 0xE027:
|
|
112
|
+
return @"-";
|
|
113
|
+
case 0xE028:
|
|
114
|
+
return @".";
|
|
115
|
+
case 0xE029:
|
|
116
|
+
return @"/";
|
|
80
117
|
default:
|
|
81
|
-
|
|
82
|
-
return 0;
|
|
118
|
+
return charCode >= 0xE000 && charCode <= 0xE05D ? @"" : value;
|
|
83
119
|
}
|
|
84
120
|
}
|
|
@@ -410,17 +410,12 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
|
|
|
410
410
|
currentItemIndex:(NSUInteger)currentItemIndex
|
|
411
411
|
{
|
|
412
412
|
NSInteger balance = 1;
|
|
413
|
-
BOOL isSelfMetaModifier = FBIsMetaModifier(self.value);
|
|
414
413
|
for (NSInteger index = currentItemIndex - 1; index >= 0; index--) {
|
|
415
414
|
FBW3CKeyItem *item = [allItems objectAtIndex:index];
|
|
416
415
|
BOOL isKeyDown = [item isKindOfClass:FBKeyDownItem.class];
|
|
417
416
|
BOOL isKeyUp = !isKeyDown && [item isKindOfClass:FBKeyUpItem.class];
|
|
418
417
|
if (!isKeyUp && !isKeyDown) {
|
|
419
|
-
|
|
420
|
-
continue;
|
|
421
|
-
} else {
|
|
422
|
-
break;
|
|
423
|
-
}
|
|
418
|
+
break;
|
|
424
419
|
}
|
|
425
420
|
|
|
426
421
|
NSString *value = [item performSelector:@selector(value)];
|
|
@@ -434,32 +429,6 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
|
|
|
434
429
|
return 0 == balance;
|
|
435
430
|
}
|
|
436
431
|
|
|
437
|
-
- (NSUInteger)collectModifersWithItems:(NSArray *)allItems
|
|
438
|
-
currentItemIndex:(NSUInteger)currentItemIndex
|
|
439
|
-
{
|
|
440
|
-
NSUInteger modifiers = 0;
|
|
441
|
-
for (NSUInteger index = 0; index < currentItemIndex; index++) {
|
|
442
|
-
FBW3CKeyItem *item = [allItems objectAtIndex:index];
|
|
443
|
-
BOOL isKeyDown = [item isKindOfClass:FBKeyDownItem.class];
|
|
444
|
-
BOOL isKeyUp = !isKeyDown && [item isKindOfClass:FBKeyUpItem.class];
|
|
445
|
-
if (!isKeyUp && !isKeyDown) {
|
|
446
|
-
continue;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
NSString *value = [item performSelector:@selector(value)];
|
|
450
|
-
NSUInteger modifier = FBToMetaModifier(value);
|
|
451
|
-
if (modifier > 0) {
|
|
452
|
-
if (isKeyDown) {
|
|
453
|
-
modifiers |= modifier;
|
|
454
|
-
} else if (item.offset < self.offset) {
|
|
455
|
-
// only cancel the modifier if it is not in the same group
|
|
456
|
-
modifiers &= ~modifier;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
return modifiers;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
432
|
- (NSString *)collectTextWithItems:(NSArray *)allItems
|
|
464
433
|
currentItemIndex:(NSUInteger)currentItemIndex
|
|
465
434
|
{
|
|
@@ -473,12 +442,8 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
|
|
|
473
442
|
}
|
|
474
443
|
|
|
475
444
|
NSString *value = [item performSelector:@selector(value)];
|
|
476
|
-
if (FBIsMetaModifier(value)) {
|
|
477
|
-
continue;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
445
|
if (isKeyUp) {
|
|
481
|
-
[result addObject:value];
|
|
446
|
+
[result addObject:FBMapIfSpecialCharacter(value)];
|
|
482
447
|
}
|
|
483
448
|
}
|
|
484
449
|
return [result.reverseObjectEnumerator.allObjects componentsJoinedByString:@""];
|
|
@@ -497,10 +462,6 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
|
|
|
497
462
|
return nil;
|
|
498
463
|
}
|
|
499
464
|
|
|
500
|
-
if (FBIsMetaModifier(self.value)) {
|
|
501
|
-
return @[];
|
|
502
|
-
}
|
|
503
|
-
|
|
504
465
|
BOOL isLastKeyUpInGroup = currentItemIndex == allItems.count - 1
|
|
505
466
|
|| [[allItems objectAtIndex:currentItemIndex + 1] isKindOfClass:FBKeyPauseItem.class];
|
|
506
467
|
if (!isLastKeyUpInGroup) {
|
|
@@ -510,10 +471,6 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
|
|
|
510
471
|
NSString *text = [self collectTextWithItems:allItems currentItemIndex:currentItemIndex];
|
|
511
472
|
NSTimeInterval offset = FBMillisToSeconds(self.offset);
|
|
512
473
|
XCPointerEventPath *resultPath = [[XCPointerEventPath alloc] initForTextInput];
|
|
513
|
-
// TODO: Figure out how meta modifiers could be applied
|
|
514
|
-
// TODO: The current approach throws zero division error on execution
|
|
515
|
-
// NSUInteger modifiers = [self collectModifersWithItems:allItems currentItemIndex:currentItemIndex];
|
|
516
|
-
// [resultPath setModifiers:modifiers mergeWithCurrentModifierFlags:NO atOffset:0];
|
|
517
474
|
[resultPath typeText:text
|
|
518
475
|
atOffset:offset
|
|
519
476
|
typingSpeed:FBConfiguration.maxTypingFrequency
|
|
@@ -555,17 +512,12 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
|
|
|
555
512
|
currentItemIndex:(NSUInteger)currentItemIndex
|
|
556
513
|
{
|
|
557
514
|
NSInteger balance = 1;
|
|
558
|
-
BOOL isSelfMetaModifier = FBIsMetaModifier(self.value);
|
|
559
515
|
for (NSUInteger index = currentItemIndex + 1; index < allItems.count; index++) {
|
|
560
516
|
FBW3CKeyItem *item = [allItems objectAtIndex:index];
|
|
561
517
|
BOOL isKeyDown = [item isKindOfClass:FBKeyDownItem.class];
|
|
562
518
|
BOOL isKeyUp = !isKeyDown && [item isKindOfClass:FBKeyUpItem.class];
|
|
563
519
|
if (!isKeyUp && !isKeyDown) {
|
|
564
|
-
|
|
565
|
-
continue;
|
|
566
|
-
} else {
|
|
567
|
-
break;
|
|
568
|
-
}
|
|
520
|
+
break;
|
|
569
521
|
}
|
|
570
522
|
|
|
571
523
|
NSString *value = [item performSelector:@selector(value)];
|
|
@@ -740,14 +692,6 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
|
|
|
740
692
|
});
|
|
741
693
|
|
|
742
694
|
NSArray<NSDictionary<NSString *, id> *> *actionItems = [actionDescription objectForKey:FB_KEY_ACTIONS];
|
|
743
|
-
if (nil == actionItems || 0 == actionItems.count) {
|
|
744
|
-
NSString *description = [NSString stringWithFormat:@"It is mandatory to have at least one item defined for each action. Action with id '%@' contains none", actionId];
|
|
745
|
-
if (error) {
|
|
746
|
-
*error = [[FBErrorBuilder.builder withDescription:description] build];
|
|
747
|
-
}
|
|
748
|
-
return nil;
|
|
749
|
-
}
|
|
750
|
-
|
|
751
695
|
FBW3CKeyItemsChain *chain = [[FBW3CKeyItemsChain alloc] init];
|
|
752
696
|
NSArray<NSDictionary<NSString *, id> *> *processedItems = [self preprocessedActionItemsWith:actionItems];
|
|
753
697
|
for (NSDictionary<NSString *, id> *actionItem in processedItems) {
|
|
@@ -818,14 +762,6 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
|
|
|
818
762
|
}
|
|
819
763
|
|
|
820
764
|
NSArray<NSDictionary<NSString *, id> *> *actionItems = [actionDescription objectForKey:FB_KEY_ACTIONS];
|
|
821
|
-
if (nil == actionItems || 0 == actionItems.count) {
|
|
822
|
-
NSString *description = [NSString stringWithFormat:@"It is mandatory to have at least one gesture item defined for each action. Action with id '%@' contains none", actionId];
|
|
823
|
-
if (error) {
|
|
824
|
-
*error = [[FBErrorBuilder.builder withDescription:description] build];
|
|
825
|
-
}
|
|
826
|
-
return nil;
|
|
827
|
-
}
|
|
828
|
-
|
|
829
765
|
FBW3CGestureItemsChain *chain = [[FBW3CGestureItemsChain alloc] init];
|
|
830
766
|
NSArray<NSDictionary<NSString *, id> *> *processedItems = [self preprocessedActionItemsWith:actionItems];
|
|
831
767
|
for (NSDictionary<NSString *, id> *actionItem in processedItems) {
|
|
@@ -900,7 +836,20 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
|
|
|
900
836
|
*error = [[FBErrorBuilder.builder withDescription:description] build];
|
|
901
837
|
}
|
|
902
838
|
return nil;
|
|
839
|
+
}
|
|
840
|
+
NSArray<NSDictionary<NSString *, id> *> *actionItems = [action objectForKey:FB_KEY_ACTIONS];
|
|
841
|
+
if (nil == actionItems) {
|
|
842
|
+
NSString *description = [NSString stringWithFormat:@"It is mandatory to have at least one item defined for each action. Action with id '%@' contains none", actionId];
|
|
843
|
+
if (error) {
|
|
844
|
+
*error = [[FBErrorBuilder.builder withDescription:description] build];
|
|
845
|
+
}
|
|
846
|
+
return nil;
|
|
903
847
|
}
|
|
848
|
+
if (0 == actionItems.count) {
|
|
849
|
+
[FBLogger logFmt:@"Action items in the action id '%@' had an empty array. Skipping the action.", actionId];
|
|
850
|
+
continue;
|
|
851
|
+
}
|
|
852
|
+
|
|
904
853
|
[actionIds addObject:actionId];
|
|
905
854
|
[actionsMapping setObject:action forKey:actionId];
|
|
906
855
|
}
|
|
@@ -140,18 +140,46 @@
|
|
|
140
140
|
@{@"type": @"keyUp", @"value": @"N"},
|
|
141
141
|
@{@"type": @"keyDown", @"value": @"B"},
|
|
142
142
|
@{@"type": @"keyUp", @"value": @"B"},
|
|
143
|
+
@{@"type": @"keyDown", @"value": @"A"},
|
|
144
|
+
@{@"type": @"keyUp", @"value": @"A"},
|
|
143
145
|
@{@"type": @"keyDown", @"value": @"a"},
|
|
144
146
|
@{@"type": @"keyUp", @"value": @"a"},
|
|
147
|
+
@{@"type": @"keyDown", @"value": [NSString stringWithFormat:@"%C", 0xE003]},
|
|
148
|
+
@{@"type": @"keyUp", @"value": [NSString stringWithFormat:@"%C", 0xE003]},
|
|
145
149
|
@{@"type": @"pause", @"duration": @500},
|
|
146
150
|
],
|
|
147
151
|
},
|
|
148
|
-
|
|
152
|
+
];
|
|
153
|
+
NSError *error;
|
|
154
|
+
XCTAssertTrue([self.testedApplication fb_performW3CActions:typeAction
|
|
155
|
+
elementCache:nil
|
|
156
|
+
error:&error]);
|
|
157
|
+
XCTAssertNil(error);
|
|
158
|
+
XCTAssertEqualObjects(textField.wdValue, @"🏀NBA");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
- (void)testTextTypingWithEmptyActions
|
|
162
|
+
{
|
|
163
|
+
if (![XCPointerEvent.class fb_areKeyEventsSupported]) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"];
|
|
168
|
+
[textField tap];
|
|
169
|
+
NSArray<NSDictionary<NSString *, id> *> *typeAction =
|
|
170
|
+
@[
|
|
171
|
+
@{
|
|
172
|
+
@"type": @"pointer",
|
|
173
|
+
@"id": @"touch",
|
|
174
|
+
@"actions": @[],
|
|
175
|
+
},
|
|
176
|
+
];
|
|
149
177
|
NSError *error;
|
|
150
178
|
XCTAssertTrue([self.testedApplication fb_performW3CActions:typeAction
|
|
151
179
|
elementCache:nil
|
|
152
180
|
error:&error]);
|
|
153
181
|
XCTAssertNil(error);
|
|
154
|
-
XCTAssertEqualObjects(textField.
|
|
182
|
+
XCTAssertEqualObjects(textField.value, @"");
|
|
155
183
|
}
|
|
156
184
|
|
|
157
185
|
@end
|