Skip to content

Commit

Permalink
Add support for generating android matchers
Browse files Browse the repository at this point in the history
This restructures the generation to allow for multiple adapters,
leaving this open for further extension. It only adds one generated
action to the live code, so that the diff doesn't get any bigger
  • Loading branch information
DanielMSchmidt committed Nov 24, 2017
1 parent a36a7d6 commit b5e1218
Show file tree
Hide file tree
Showing 19 changed files with 925 additions and 411 deletions.
5 changes: 3 additions & 2 deletions detox/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@
"Emulator.js",
"DeviceDriverBase.js",
"GREYConfiguration.js",
"src/ios/earlgreyapi",
"src/utils/environment.js",
"AAPT.js",
"ADB.js",
"fsext.js"
"fsext.js",
"src/ios/earlgreyapi",
"src/android/espressoapi"
],
"resetMocks": true,
"resetModules": true,
Expand Down
142 changes: 142 additions & 0 deletions detox/src/android/espressoapi/DetoxAction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/**
This code is generated.
For more information see generation/README.md.
*/


// Globally declared helpers

function sanitize_greyDirection(action) {
switch (action) {
case "left":
return 1;
case "right":
return 2;
case "up":
return 3;
case "down":
return 4;

default:
throw new Error(`GREYAction.GREYDirection must be a 'left'/'right'/'up'/'down', got ${action}`);
}
}

function sanitize_greyContentEdge(action) {
switch (action) {
case "left":
return 0;
case "right":
return 1;
case "top":
return 2;
case "bottom":
return 3;

default:
throw new Error(`GREYAction.GREYContentEdge must be a 'left'/'right'/'top'/'bottom', got ${action}`);
}
}

function sanitize_uiAccessibilityTraits(value) {
let traits = 0;
for (let i = 0; i < value.length; i++) {
switch (value[i]) {
case 'button': traits |= 1; break;
case 'link': traits |= 2; break;
case 'header': traits |= 4; break;
case 'search': traits |= 8; break;
case 'image': traits |= 16; break;
case 'selected': traits |= 32; break;
case 'plays': traits |= 64; break;
case 'key': traits |= 128; break;
case 'text': traits |= 256; break;
case 'summary': traits |= 512; break;
case 'disabled': traits |= 1024; break;
case 'frequentUpdates': traits |= 2048; break;
case 'startsMedia': traits |= 4096; break;
case 'adjustable': traits |= 8192; break;
case 'allowsDirectInteraction': traits |= 16384; break;
case 'pageTurn': traits |= 32768; break;
default: throw new Error(`Unknown trait '${value[i]}', see list in https://facebook.github.io/react-native/docs/accessibility.html#accessibilitytraits-ios`);
}
}

return traits;
}



class DetoxAction {
static multiClick(times) {
if (typeof times !== "number") throw new Error("times should be a number, but got " + (times + (" (" + (typeof times + ")"))));
return {
target: {
type: "Class",
value: "com.wix.detox.espresso.DetoxAction"
},
method: "multiClick",
args: [{
type: "Integer",
value: times
}]
};
}

static tapAtLocation(x, y) {
if (typeof x !== "number") throw new Error("x should be a number, but got " + (x + (" (" + (typeof x + ")"))));
if (typeof y !== "number") throw new Error("y should be a number, but got " + (y + (" (" + (typeof y + ")"))));
return {
target: {
type: "Class",
value: "com.wix.detox.espresso.DetoxAction"
},
method: "tapAtLocation",
args: [{
type: "Integer",
value: x
}, {
type: "Integer",
value: y
}]
};
}

static scrollToEdge(edge) {
if (typeof edge !== "number") throw new Error("edge should be a number, but got " + (edge + (" (" + (typeof edge + ")"))));
return {
target: {
type: "Class",
value: "com.wix.detox.espresso.DetoxAction"
},
method: "scrollToEdge",
args: [{
type: "Integer",
value: edge
}]
};
}

static scrollInDirection(direction, amountInDP) {
if (typeof direction !== "number") throw new Error("direction should be a number, but got " + (direction + (" (" + (typeof direction + ")"))));
if (typeof amountInDP !== "number") throw new Error("amountInDP should be a number, but got " + (amountInDP + (" (" + (typeof amountInDP + ")"))));
return {
target: {
type: "Class",
value: "com.wix.detox.espresso.DetoxAction"
},
method: "scrollInDirection",
args: [{
type: "Integer",
value: direction
}, {
type: "double",
value: amountInDP
}]
};
}

}

module.exports = DetoxAction;
3 changes: 2 additions & 1 deletion detox/src/android/expect.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const invoke = require('../invoke');
const matchers = require('./matcher');
const DetoxActionApi = require('./espressoapi/DetoxAction');
const Matcher = matchers.Matcher;
const LabelMatcher = matchers.LabelMatcher;
const IdMatcher = matchers.IdMatcher;
Expand Down Expand Up @@ -51,7 +52,7 @@ class LongPressAction extends Action {
class MultiClickAction extends Action {
constructor(times) {
super();
this._call = invoke.call(invoke.Android.Class(DetoxAction), 'multiClick', invoke.Android.Integer(times));
this._call = invoke.callDirectly(DetoxActionApi.multiClick(times));
}
}

Expand Down
19 changes: 19 additions & 0 deletions generation/__tests__/__snapshots__/android.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Android generation methods should generate type checks 1`] = `"times should be a number, but got FOO (string)"`;

exports[`Android generation methods should return adapter calls 1`] = `
Object {
"args": Array [
Object {
"type": "Integer",
"value": 3,
},
],
"method": "multiClick",
"target": Object {
"type": "Class",
"value": "com.wix.detox.espresso.DetoxAction",
},
}
`;
100 changes: 0 additions & 100 deletions generation/__tests__/__snapshots__/earl-grey.js.snap

This file was deleted.

100 changes: 100 additions & 0 deletions generation/__tests__/__snapshots__/ios.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`iOS generation Error handling should thow error for CGPoint with wrong x and y values 1`] = `"point.x should be a number, but got 3 (string)"`;

exports[`iOS generation Error handling should thow error for CGPoint with wrong x and y values 2`] = `"point.y should be a number, but got undefined (undefined)"`;

exports[`iOS generation Error handling should throw error for not in accepted range 1`] = `"direction should be one of [left, right, up, down], but got flipside"`;

exports[`iOS generation Error handling should throw error for wrong type 1`] = `"count should be a number, but got foo (string)"`;

exports[`iOS generation Error handling should throw error for wrong type 2`] = `"point should be a object, but got 4 (number)"`;

exports[`iOS generation Invocations should return the invocation object for methods 1`] = `
Object {
"args": Array [
Object {
"type": "NSInteger",
"value": 3,
},
],
"method": "actionForMultipleTapsWithCount:",
"target": Object {
"type": "Class",
"value": "GREYActions",
},
}
`;

exports[`iOS generation Invocations should return the invocation object for methods with objects as args 1`] = `
Object {
"args": Array [
Object {
"type": "NSInteger",
"value": 3,
},
Object {
"type": "CGPoint",
"value": Object {
"x": 3,
"y": 4,
},
},
],
"method": "actionForMultipleTapsWithCount:atPoint:",
"target": Object {
"type": "Class",
"value": "GREYActions",
},
}
`;

exports[`iOS generation Invocations should return the invocation object for methods with strings 1`] = `
Object {
"args": Array [
Object {
"type": "NSString",
"value": "Foo",
},
],
"method": "actionForTypeText:",
"target": Object {
"type": "Class",
"value": "GREYActions",
},
}
`;

exports[`iOS generation Invocations should sanitize the directions 1`] = `
Object {
"args": Array [
Object {
"type": "NSInteger",
"value": 4,
},
Object {
"type": "CGFloat",
"value": 3,
},
Object {
"type": "CGFloat",
"value": 4,
},
Object {
"type": "CGFloat",
"value": 5,
},
],
"method": "actionForScrollInDirection:amount:xOriginStartPercentage:yOriginStartPercentage:",
"target": Object {
"type": "Class",
"value": "GREYActions",
},
}
`;

exports[`iOS generation special case: id<GREYMatcher> should fail with wrongly formatted matchers 1`] = `"firstMatcher should be a GREYMatcher, but got {\\"type\\":\\"Invocation\\",\\"value\\":{\\"target\\":{\\"type\\":\\"Class\\",\\"value\\":\\"GREYAction\\"},\\"method\\":\\"matcherForAccessibilityID:\\",\\"args\\":[\\"Grandfather883\\"]}}"`;
exports[`iOS generation special case: id<GREYMatcher> should fail with wrongly formatted matchers 2`] = `"ancestorMatcher should be a GREYMatcher, but got {\\"type\\":\\"Invocation\\",\\"value\\":{\\"target\\":{\\"type\\":\\"Class\\",\\"value\\":\\"GREYAction\\"},\\"method\\":\\"matcherForAccessibilityID:\\",\\"args\\":[\\"Grandson883\\"]}}"`;
exports[`iOS generation special case: id<GREYMatcher> should fail with wrongly formatted matchers 3`] = `"firstMatcher should be a GREYMatcher, but got {\\"type\\":\\"Invocation\\",\\"value\\":{\\"method\\":\\"matcherForAccessibilityID:\\",\\"args\\":[\\"Grandfather883\\"]}}"`;
Loading

0 comments on commit b5e1218

Please sign in to comment.