Skip to content

Commit 47d9537

Browse files
committed
feat: steps automatic creation for Android
1 parent ea7757f commit 47d9537

File tree

9 files changed

+590
-0
lines changed

9 files changed

+590
-0
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { androidDescriptionMaker } from './android-description-maker';
2+
3+
describe('Android description maker', () => {
4+
test('should handle basic tap by test ID', () => {
5+
const payload = {
6+
type: 'invoke',
7+
params: {
8+
target: { type: 'Class', value: 'com.wix.detox.espresso.EspressoDetox' },
9+
method: 'perform',
10+
args: [
11+
{
12+
type: 'Invocation',
13+
value: {
14+
target: { type: 'Class', value: 'com.wix.detox.espresso.DetoxMatcher' },
15+
method: 'matcherForTestId',
16+
args: ['SimpleButton', { type: 'Boolean', value: false }],
17+
},
18+
},
19+
{
20+
type: 'Invocation',
21+
value: {
22+
target: { type: 'Class', value: 'com.wix.detox.espresso.DetoxViewActions' },
23+
method: 'click',
24+
args: [],
25+
},
26+
},
27+
],
28+
},
29+
};
30+
31+
const description = androidDescriptionMaker(payload);
32+
expect(description).toEqual({
33+
message: 'Click on #SimpleButton',
34+
args: { id: 'SimpleButton' },
35+
});
36+
});
37+
38+
test('should handle scroll with text matcher', () => {
39+
const payload = {
40+
type: 'invoke',
41+
params: {
42+
target: { type: 'Class', value: 'com.wix.detox.espresso.DetoxAction' },
43+
method: 'scrollInDirection',
44+
args: [
45+
'down',
46+
{ type: 'Integer', value: 50 },
47+
{ type: 'Double', value: 0.2 },
48+
{ type: 'Double', value: 0.4 },
49+
{
50+
type: 'Invocation',
51+
value: {
52+
target: { type: 'Class', value: 'com.wix.detox.espresso.DetoxMatcher' },
53+
method: 'matcherForText',
54+
args: ['Index', { type: 'Boolean', value: false }],
55+
},
56+
},
57+
],
58+
},
59+
};
60+
61+
const description = androidDescriptionMaker(payload);
62+
expect(description).toEqual({
63+
message: 'Scroll down on "Index"',
64+
args: {
65+
direction: 'down',
66+
amount: 50,
67+
text: 'Index',
68+
},
69+
});
70+
});
71+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import type { StepDescriptionMaker } from '../types';
2+
import type { DetoxMessage } from './detox-payload';
3+
import { formatAndroidMessage } from './formatters';
4+
5+
export const androidDescriptionMaker: StepDescriptionMaker = (payload: unknown) => {
6+
const message = payload as DetoxMessage;
7+
return formatAndroidMessage(message);
8+
};
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
// eslint-disable-next-line @typescript-eslint/ban-types
2+
export const classRegistry: Record<string, Record<string, Function>> = {
3+
'androidx.test.espresso.Espresso': {
4+
onView<T>(_viewMatcher: T) {
5+
return _viewMatcher;
6+
},
7+
},
8+
'androidx.test.espresso.action.ViewActions': {
9+
clearGlobalAssertions() {},
10+
actionWithAssertions(_viewAction: any) {},
11+
clearText() {},
12+
click(_inputDevice?: any, _buttonState?: any) {},
13+
swipeLeft() {},
14+
swipeRight() {},
15+
swipeDown() {},
16+
swipeUp() {},
17+
closeSoftKeyboard() {},
18+
pressImeActionButton() {},
19+
pressBack() {},
20+
pressBackUnconditionally() {},
21+
pressMenuKey() {},
22+
pressKey(_keyCode: any) {},
23+
doubleClick() {},
24+
longClick() {},
25+
scrollTo() {},
26+
typeTextIntoFocusedView(_stringToBeTyped: any) {},
27+
typeText(_stringToBeTyped: any) {},
28+
replaceText(_stringToBeSet: any) {},
29+
openLinkWithText(_linkText: any) {},
30+
openLinkWithUri(_uri: any) {},
31+
repeatedlyUntil(_action: any, _desiredStateMatcher: any, _maxAttempts: any) {},
32+
},
33+
'com.wix.detox.Detox': {
34+
setUpCustomEspressoIdlingResources() {},
35+
runDetoxTests() {},
36+
launchMainActivity() {},
37+
startActivityFromUrl(_url: any) {},
38+
startActivityFromNotification(_dataFilePath: any) {},
39+
getAppContext() {},
40+
generateViewHierarchyXml(_shouldInjectTestIds: any) {},
41+
},
42+
'com.wix.detox.espresso.DetoxAction': {
43+
multiClick(_times: any) {},
44+
tapAtLocation(_x: any, _y: any) {},
45+
createCoordinatesProvider(_x: any, _y: any) {},
46+
scrollToEdge(_edge: any, _startOffsetPercentX: any, _startOffsetPercentY: any) {},
47+
scrollInDirection(
48+
_direction: any,
49+
_amountInDP: any,
50+
_startOffsetPercentX: any,
51+
_startOffsetPercentY: any,
52+
) {},
53+
scrollInDirectionStaleAtEdge(
54+
_direction: any,
55+
_amountInDP: any,
56+
_startOffsetPercentX: any,
57+
_startOffsetPercentY: any,
58+
) {},
59+
swipeInDirection(
60+
_direction: any,
61+
_fast: any,
62+
_normalizedOffset: any,
63+
_normalizedStartingPointX: any,
64+
_normalizedStartingPointY: any,
65+
) {},
66+
getAttributes() {},
67+
scrollToIndex(_index: any) {},
68+
setDatePickerDate(_dateString: any, _formatString: any) {},
69+
adjustSliderToPosition(_newPosition: any) {},
70+
longPressAndDrag(
71+
_duration: any,
72+
_normalizedPositionX: any,
73+
_normalizedPositionY: any,
74+
_targetElement: any,
75+
_normalizedTargetPositionX: any,
76+
_normalizedTargetPositionY: any,
77+
_isFast: any,
78+
_holdDuration: any,
79+
) {},
80+
longPress(_x?: any, _y?: any, _duration?: any) {},
81+
takeViewScreenshot() {},
82+
accessibilityAction(_actionName: any) {},
83+
parseDateISO8601(_dateString: any) {},
84+
},
85+
'com.wix.detox.espresso.DetoxAssertion': {
86+
assertMatcher(_viewInteraction: any, _viewMatcher: any) {},
87+
assertNotVisible(_viewInteraction: any) {},
88+
assertNotExists(_viewInteraction: any) {},
89+
waitForAssertMatcher(_viewInteraction: any, _viewMatcher: any, _timeoutSeconds: any) {},
90+
waitForAssertMatcherWithSearchAction(
91+
_viewInteraction: any,
92+
_viewMatcher: any,
93+
_searchAction: any,
94+
_searchMatcher: any,
95+
) {},
96+
},
97+
'com.wix.detox.espresso.DetoxMatcher': {
98+
matcherForText(_text: any, _isRegex: any) {},
99+
matcherForAccessibilityLabel(_label: any, _isRegex: any) {},
100+
matcherForShallowAccessibilityLabel(_label: any, _isRegex: any) {},
101+
matcherForContentDescription(_contentDescription: any) {},
102+
matcherForTestId(_testId: any, _isRegex: any) {},
103+
matcherForToggleable(_value: any) {},
104+
matcherForAnd(_m1: any, _m2: any) {},
105+
matcherForOr(_m1: any, _m2: any) {},
106+
matcherForNot(_m: any) {},
107+
matcherWithAncestor(_m: any, _ancestorMatcher: any) {},
108+
matcherWithDescendant(_m: any, _descendantMatcher: any) {},
109+
matcherForClass(_className: any) {},
110+
matcherForSufficientlyVisible(_pct: any) {},
111+
matcherForNotVisible() {},
112+
matcherForNotNull() {},
113+
matcherForNull() {},
114+
matcherForAtIndex(_index: any, _innerMatcher: any) {},
115+
matcherForAnything() {},
116+
matcherForFocus() {},
117+
matcherForSliderPosition(_position: any, _tolerance: any) {},
118+
},
119+
'com.wix.detox.espresso.DetoxViewActions': {
120+
click() {},
121+
typeText(_text: any) {},
122+
},
123+
'com.wix.detox.espresso.EspressoDetox': {
124+
perform(_matcher: any, _action: any) {},
125+
changeOrientation(_orientation: any) {},
126+
setSynchronization(_enabled: any) {},
127+
setURLBlacklist(_urls: any) {},
128+
tap(_x: any, _y: any, _shouldIgnoreStatusBar: any) {},
129+
longPress(_x: any, _y: any, _shouldIgnoreStatusBar: any, _duration?: any) {},
130+
},
131+
'com.wix.detox.espresso.web.DetoxWebAtomMatcher': {
132+
matcherForId(_id: any) {},
133+
matcherForClassName(_className: any) {},
134+
matcherForCssSelector(_cssSelector: any) {},
135+
matcherForName(_name: any) {},
136+
matcherForXPath(_xpath: any) {},
137+
matcherForLinkText(_linkText: any) {},
138+
matcherForPartialLinkText(_partialLinkText: any) {},
139+
matcherForTagName(_tag: any) {},
140+
},
141+
'com.wix.detox.espresso.web.EspressoWebDetox': {
142+
getWebView(_matcher?: any) {},
143+
expect(_webElement: any) {},
144+
},
145+
'com.wix.detox.espresso.web.WebElement': {
146+
tap(_element: any) {},
147+
typeText(_element: any, _text: any) {},
148+
replaceText(_element: any, _text: any) {},
149+
clearText(_element: any) {},
150+
scrollToView(_element: any) {},
151+
getText(_element: any) {},
152+
runScript(_element: any, _script: any) {},
153+
runScriptWithArgs(_element: any, _script: any, _args: any) {},
154+
getCurrentUrl(_element: any) {},
155+
getTitle(_element: any) {},
156+
},
157+
'com.wix.detox.espresso.web.WebExpect': {
158+
toNotExist(_element: any) {},
159+
toExist(_element: any) {},
160+
toHaveText(_element: any, _text: any) {},
161+
toNotHaveText(_element: any, _text: any) {},
162+
},
163+
'com.wix.detox.espresso.web.WebViewElement': {
164+
element(_element: any, _webMatcher: any, _index?: any) {},
165+
},
166+
'com.wix.detox.genymotion.DetoxGenymotionManager': {
167+
setLocation(_lat: any, _lon: any) {},
168+
getGenymotionManager() {},
169+
},
170+
'com.wix.detox.uiautomator.UiAutomator': {
171+
uiDevice() {
172+
return {
173+
click(_x: any, _y: any) {},
174+
pressBack() {},
175+
pressKeyCode(_keyCode: any, _metaState?: any) {},
176+
swipe(_startX: any, _startY: any, _endX: any, _endY: any, _steps: any) {},
177+
setCompressedLayoutHeirarchy(_compressed: any) {},
178+
getInstance() {},
179+
getDisplaySizeDp() {},
180+
getProductName() {},
181+
getLastTraversedText() {},
182+
clearLastTraversedText() {},
183+
pressMenu() {},
184+
pressHome() {},
185+
pressSearch() {},
186+
pressDPadCenter() {},
187+
pressDPadDown() {},
188+
pressDPadUp() {},
189+
pressDPadLeft() {},
190+
pressDPadRight() {},
191+
pressDelete() {},
192+
pressEnter() {},
193+
pressRecentApps() {},
194+
openNotification() {},
195+
openQuickSettings() {},
196+
getDisplayWidth() {},
197+
getDisplayHeight() {},
198+
drag(_startX: any, _startY: any, _endX: any, _endY: any, _steps: any) {},
199+
waitForIdle() {},
200+
getCurrentActivityName() {},
201+
getCurrentPackageName() {},
202+
removeWatcher(_name: any) {},
203+
runWatchers() {},
204+
resetWatcherTriggers() {},
205+
hasWatcherTriggered(_watcherName: any) {},
206+
hasAnyWatcherTriggered() {},
207+
setWatcherTriggered(_watcherName: any) {},
208+
isNaturalOrientation() {},
209+
getDisplayRotation() {},
210+
freezeRotation() {},
211+
unfreezeRotation() {},
212+
setOrientationLeft() {},
213+
setOrientationRight() {},
214+
setOrientationNatural() {},
215+
wakeUp() {},
216+
isScreenOn() {},
217+
sleep() {},
218+
dumpWindowHierarchy(_fileName: any) {},
219+
};
220+
},
221+
},
222+
};
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
export type DetoxMessage = InvocationMessage;
2+
3+
export interface InvocationMessage {
4+
type: 'invoke';
5+
params?: InvocationValue;
6+
}
7+
8+
export interface InvocationObject {
9+
type: 'Invocation';
10+
value: InvocationValue;
11+
}
12+
13+
export interface ClassObject {
14+
type: 'Class';
15+
value: string;
16+
}
17+
18+
export interface BooleanObject {
19+
type: 'Boolean';
20+
value: boolean;
21+
}
22+
23+
export interface DoubleObject {
24+
type: 'Double';
25+
value: number;
26+
}
27+
28+
export interface IntegerObject {
29+
type: 'Integer';
30+
value: number;
31+
}
32+
33+
export interface InvocationValue {
34+
target: Target;
35+
method: string;
36+
args: unknown[];
37+
}
38+
39+
export interface Target {
40+
type?: string;
41+
value?: string;
42+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
export type DetoxMessage = InvocationMessage;
2+
3+
export interface InvocationMessage {
4+
type: 'invoke';
5+
params?: InvocationValue;
6+
}
7+
8+
export interface InvocationValue {
9+
target: Target;
10+
method: string;
11+
args: unknown[];
12+
}
13+
14+
export type Target = ClassObject | BooleanObject | DoubleObject | IntegerObject | string;
15+
16+
export interface BaseTarget {
17+
type?: string;
18+
value?: unknown;
19+
}
20+
21+
export interface ClassObject extends BaseTarget {
22+
type: 'Class';
23+
value: string;
24+
}
25+
26+
export interface BooleanObject extends BaseTarget {
27+
type: 'Boolean';
28+
value: boolean;
29+
}
30+
31+
export interface DoubleObject extends BaseTarget {
32+
type: 'Double';
33+
value: number;
34+
}
35+
36+
export interface IntegerObject extends BaseTarget {
37+
type: 'Integer';
38+
value: number;
39+
}
40+
41+
export interface InvocationObject extends BaseTarget {
42+
type: 'Invocation';
43+
value: InvocationValue;
44+
}
45+
46+
// Our basic type for a step description used in Allure
47+
export interface StepDescription {
48+
message: string;
49+
args: Record<string, any> | null | undefined;
50+
}

0 commit comments

Comments
 (0)