Skip to content

Commit

Permalink
add Matcher<View> type to generated code
Browse files Browse the repository at this point in the history
Besides that also strings are now send unwrapped, as in the unchanged
code before
  • Loading branch information
DanielMSchmidt committed Jan 16, 2018
1 parent b3273d9 commit 6783520
Show file tree
Hide file tree
Showing 12 changed files with 321 additions and 66 deletions.
183 changes: 168 additions & 15 deletions detox/src/android/espressoapi/DetoxMatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
*/



function sanitize_matcher(matcher) {
const originalMatcher =
typeof matcher._call === "function" ? matcher._call() : matcher._call;
return originalMatcher.type ? originalMatcher.value : originalMatcher;
}
class DetoxMatcher {
static matcherForText(text) {
if (typeof text !== "string") throw new Error("text should be a string, but got " + (text + (" (" + (typeof text + ")"))));
Expand All @@ -15,10 +19,7 @@ class DetoxMatcher {
value: "com.wix.detox.espresso.DetoxMatcher"
},
method: "matcherForText",
args: [{
type: "String",
value: text
}]
args: [text]
};
}

Expand All @@ -30,10 +31,7 @@ class DetoxMatcher {
value: "com.wix.detox.espresso.DetoxMatcher"
},
method: "matcherForContentDescription",
args: [{
type: "String",
value: contentDescription
}]
args: [contentDescription]
};
}

Expand All @@ -45,9 +43,142 @@ class DetoxMatcher {
value: "com.wix.detox.espresso.DetoxMatcher"
},
method: "matcherForTestId",
args: [testId]
};
}

static matcherForAnd(m1, m2) {
if (typeof m1 !== 'object' || typeof m1.constructor !== 'function' || m1.constructor.name.indexOf('Matcher') === -1) {
const isObject = typeof m1 === 'object';
const additionalErrorInfo = isObject ? typeof m1.constructor === 'object' ? 'the constructor is no object' : 'it has a wrong class name: "' + m1.constructor.name + '"' : 'it is no object';
throw new Error('m1 should be an instance of Matcher, got "' + m1 + '", it appears that ' + additionalErrorInfo);
}

if (typeof m2 !== 'object' || typeof m2.constructor !== 'function' || m2.constructor.name.indexOf('Matcher') === -1) {
const isObject = typeof m2 === 'object';
const additionalErrorInfo = isObject ? typeof m2.constructor === 'object' ? 'the constructor is no object' : 'it has a wrong class name: "' + m2.constructor.name + '"' : 'it is no object';
throw new Error('m2 should be an instance of Matcher, got "' + m2 + '", it appears that ' + additionalErrorInfo);
}

return {
target: {
type: "Class",
value: "com.wix.detox.espresso.DetoxMatcher"
},
method: "matcherForAnd",
args: [{
type: "Invocation",
value: sanitize_matcher(m1)
}, {
type: "Invocation",
value: sanitize_matcher(m2)
}]
};
}

static matcherForOr(m1, m2) {
if (typeof m1 !== 'object' || typeof m1.constructor !== 'function' || m1.constructor.name.indexOf('Matcher') === -1) {
const isObject = typeof m1 === 'object';
const additionalErrorInfo = isObject ? typeof m1.constructor === 'object' ? 'the constructor is no object' : 'it has a wrong class name: "' + m1.constructor.name + '"' : 'it is no object';
throw new Error('m1 should be an instance of Matcher, got "' + m1 + '", it appears that ' + additionalErrorInfo);
}

if (typeof m2 !== 'object' || typeof m2.constructor !== 'function' || m2.constructor.name.indexOf('Matcher') === -1) {
const isObject = typeof m2 === 'object';
const additionalErrorInfo = isObject ? typeof m2.constructor === 'object' ? 'the constructor is no object' : 'it has a wrong class name: "' + m2.constructor.name + '"' : 'it is no object';
throw new Error('m2 should be an instance of Matcher, got "' + m2 + '", it appears that ' + additionalErrorInfo);
}

return {
target: {
type: "Class",
value: "com.wix.detox.espresso.DetoxMatcher"
},
method: "matcherForOr",
args: [{
type: "Invocation",
value: sanitize_matcher(m1)
}, {
type: "Invocation",
value: sanitize_matcher(m2)
}]
};
}

static matcherForNot(m) {
if (typeof m !== 'object' || typeof m.constructor !== 'function' || m.constructor.name.indexOf('Matcher') === -1) {
const isObject = typeof m === 'object';
const additionalErrorInfo = isObject ? typeof m.constructor === 'object' ? 'the constructor is no object' : 'it has a wrong class name: "' + m.constructor.name + '"' : 'it is no object';
throw new Error('m should be an instance of Matcher, got "' + m + '", it appears that ' + additionalErrorInfo);
}

return {
target: {
type: "Class",
value: "com.wix.detox.espresso.DetoxMatcher"
},
method: "matcherForNot",
args: [{
type: "String",
value: testId
type: "Invocation",
value: sanitize_matcher(m)
}]
};
}

static matcherWithAncestor(m, ancestorMatcher) {
if (typeof m !== 'object' || typeof m.constructor !== 'function' || m.constructor.name.indexOf('Matcher') === -1) {
const isObject = typeof m === 'object';
const additionalErrorInfo = isObject ? typeof m.constructor === 'object' ? 'the constructor is no object' : 'it has a wrong class name: "' + m.constructor.name + '"' : 'it is no object';
throw new Error('m should be an instance of Matcher, got "' + m + '", it appears that ' + additionalErrorInfo);
}

if (typeof ancestorMatcher !== 'object' || typeof ancestorMatcher.constructor !== 'function' || ancestorMatcher.constructor.name.indexOf('Matcher') === -1) {
const isObject = typeof ancestorMatcher === 'object';
const additionalErrorInfo = isObject ? typeof ancestorMatcher.constructor === 'object' ? 'the constructor is no object' : 'it has a wrong class name: "' + ancestorMatcher.constructor.name + '"' : 'it is no object';
throw new Error('ancestorMatcher should be an instance of Matcher, got "' + ancestorMatcher + '", it appears that ' + additionalErrorInfo);
}

return {
target: {
type: "Class",
value: "com.wix.detox.espresso.DetoxMatcher"
},
method: "matcherWithAncestor",
args: [{
type: "Invocation",
value: sanitize_matcher(m)
}, {
type: "Invocation",
value: sanitize_matcher(ancestorMatcher)
}]
};
}

static matcherWithDescendant(m, descendantMatcher) {
if (typeof m !== 'object' || typeof m.constructor !== 'function' || m.constructor.name.indexOf('Matcher') === -1) {
const isObject = typeof m === 'object';
const additionalErrorInfo = isObject ? typeof m.constructor === 'object' ? 'the constructor is no object' : 'it has a wrong class name: "' + m.constructor.name + '"' : 'it is no object';
throw new Error('m should be an instance of Matcher, got "' + m + '", it appears that ' + additionalErrorInfo);
}

if (typeof descendantMatcher !== 'object' || typeof descendantMatcher.constructor !== 'function' || descendantMatcher.constructor.name.indexOf('Matcher') === -1) {
const isObject = typeof descendantMatcher === 'object';
const additionalErrorInfo = isObject ? typeof descendantMatcher.constructor === 'object' ? 'the constructor is no object' : 'it has a wrong class name: "' + descendantMatcher.constructor.name + '"' : 'it is no object';
throw new Error('descendantMatcher should be an instance of Matcher, got "' + descendantMatcher + '", it appears that ' + additionalErrorInfo);
}

return {
target: {
type: "Class",
value: "com.wix.detox.espresso.DetoxMatcher"
},
method: "matcherWithDescendant",
args: [{
type: "Invocation",
value: sanitize_matcher(m)
}, {
type: "Invocation",
value: sanitize_matcher(descendantMatcher)
}]
};
}
Expand All @@ -60,10 +191,7 @@ class DetoxMatcher {
value: "com.wix.detox.espresso.DetoxMatcher"
},
method: "matcherForClass",
args: [{
type: "String",
value: className
}]
args: [className]
};
}

Expand Down Expand Up @@ -111,6 +239,31 @@ class DetoxMatcher {
};
}

static matcherForAtIndex(index, innerMatcher) {
if (typeof index !== "number") throw new Error("index should be a number, but got " + (index + (" (" + (typeof index + ")"))));

if (typeof innerMatcher !== 'object' || typeof innerMatcher.constructor !== 'function' || innerMatcher.constructor.name.indexOf('Matcher') === -1) {
const isObject = typeof innerMatcher === 'object';
const additionalErrorInfo = isObject ? typeof innerMatcher.constructor === 'object' ? 'the constructor is no object' : 'it has a wrong class name: "' + innerMatcher.constructor.name + '"' : 'it is no object';
throw new Error('innerMatcher should be an instance of Matcher, got "' + innerMatcher + '", it appears that ' + additionalErrorInfo);
}

return {
target: {
type: "Class",
value: "com.wix.detox.espresso.DetoxMatcher"
},
method: "matcherForAtIndex",
args: [{
type: "Integer",
value: index
}, {
type: "Invocation",
value: sanitize_matcher(innerMatcher)
}]
};
}

static matcherForAnything() {
return {
target: {
Expand Down
25 changes: 5 additions & 20 deletions detox/src/android/espressoapi/ViewActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,7 @@ class ViewActions {
value: "android.support.test.espresso.action.ViewActions"
},
method: "typeTextIntoFocusedView",
args: [{
type: "String",
value: stringToBeTyped
}]
args: [stringToBeTyped]
};
}

Expand All @@ -199,10 +196,7 @@ class ViewActions {
value: "android.support.test.espresso.action.ViewActions"
},
method: "typeText",
args: [{
type: "String",
value: stringToBeTyped
}]
args: [stringToBeTyped]
};
}

Expand All @@ -214,10 +208,7 @@ class ViewActions {
value: "android.support.test.espresso.action.ViewActions"
},
method: "replaceText",
args: [{
type: "String",
value: stringToBeSet
}]
args: [stringToBeSet]
};
}

Expand All @@ -229,10 +220,7 @@ class ViewActions {
value: "android.support.test.espresso.action.ViewActions"
},
method: "openLinkWithText",
args: [{
type: "String",
value: linkText
}]
args: [linkText]
};
}

Expand All @@ -244,10 +232,7 @@ class ViewActions {
value: "android.support.test.espresso.action.ViewActions"
},
method: "openLinkWithUri",
args: [{
type: "String",
value: uri
}]
args: [uri]
};
}

Expand Down
31 changes: 9 additions & 22 deletions detox/src/android/matcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,23 @@ const DetoxMatcher = 'com.wix.detox.espresso.DetoxMatcher';

class Matcher {
withAncestor(matcher) {
if (!(matcher instanceof Matcher)) throw new Error(`Matcher withAncestor argument must be a valid Matcher, got ${typeof matcher}`);
const _originalMatcherCall = this._call;
this._call = invoke.call(invoke.Android.Class(DetoxMatcher), 'matcherWithAncestor', _originalMatcherCall, matcher._call);
this._call = invoke.callDirectly(DetoxMatcherApi.matcherWithAncestor(this, matcher));
return this;
}
withDescendant(matcher) {
if (!(matcher instanceof Matcher)) throw new Error(`Matcher withDescendant argument must be a valid Matcher, got ${typeof matcher}`);
const _originalMatcherCall = this._call;
this._call = invoke.call(invoke.Android.Class(DetoxMatcher), 'matcherWithDescendant', _originalMatcherCall, matcher._call);
this._call = invoke.callDirectly(DetoxMatcherApi.matcherWithDescendant(this, matcher));
return this;
}
and(matcher) {
if (!(matcher instanceof Matcher)) throw new Error(`Matcher and argument must be a valid Matcher, got ${typeof matcher}`);
const _originalMatcherCall = this._call;
this._call = invoke.call(invoke.Android.Class(DetoxMatcher), 'matcherForAnd', _originalMatcherCall, matcher._call);
this._call = invoke.callDirectly(DetoxMatcherApi.matcherForAnd(this, matcher));
return this;
}
or(matcher) {
if (!(matcher instanceof Matcher)) throw new Error(`Matcher and argument must be a valid Matcher, got ${typeof matcher}`);
const _originalMatcherCall = this._call;
this._call = invoke.call(invoke.Android.Class(DetoxMatcher), 'matcherForOr', _originalMatcherCall, matcher._call);
this._call = invoke.callDirectly(DetoxMatcherApi.matcherForOr(this, matcher));
return this;
}
not() {
const _originalMatcherCall = this._call;
this._call = invoke.call(invoke.Android.Class(DetoxMatcher), 'matcherForNot', _originalMatcherCall);
this._call = invoke.callDirectly(DetoxMatcherApi.matcherForNot(this));
return this;
}

Expand Down Expand Up @@ -62,16 +53,14 @@ class LabelMatcher extends Matcher {
class IdMatcher extends Matcher {
constructor(value) {
super();
if (typeof value !== 'string') throw new Error(`IdMatcher ctor argument must be a string, got ${typeof value}`);
this._call = invoke.call(invoke.Android.Class(DetoxMatcher), 'matcherForTestId', value);
this._call = invoke.callDirectly(DetoxMatcherApi.matcherForTestId(value));
}
}

class TypeMatcher extends Matcher {
constructor(value) {
super();
if (typeof value !== 'string') throw new Error(`TypeMatcher ctor argument must be a string, got ${typeof value}`);
this._call = invoke.call(invoke.Android.Class(DetoxMatcher), 'matcherForClass', value);
this._call = invoke.callDirectly(DetoxMatcherApi.matcherForClass(value));
}
}

Expand Down Expand Up @@ -106,16 +95,14 @@ class NotExistsMatcher extends Matcher {
class TextMatcher extends Matcher {
constructor(value) {
super();
if (typeof value !== 'string') throw new Error(`TextMatcher ctor argument must be a string, got ${typeof value}`);
this._call = invoke.call(invoke.Android.Class(DetoxMatcher), 'matcherForText', value);
this._call = invoke.callDirectly(DetoxMatcherApi.matcherForText(value));
}
}

class ValueMatcher extends Matcher {
constructor(value) {
super();
if (typeof value !== 'string') throw new Error(`ValueMatcher ctor argument must be a string, got ${typeof value}`);
this._call = invoke.call(invoke.Android.Class(DetoxMatcher), 'matcherForContentDescription', value);
this._call = invoke.callDirectly(DetoxMatcherApi.matcherForContentDescription(value));
}
}

Expand Down
2 changes: 1 addition & 1 deletion detox/test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"binaryPath": "android/app/build/outputs/apk/release/app-release.apk",
"build": "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..",
"type": "android.emulator",
"name": "Nexus_5X_API_26"
"name": "Nexus_5X_API_27_x86"
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions generation/__tests__/__snapshots__/android.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ Object {
},
}
`;

exports[`Android generation validation Matcher<View> should fail getting no object 1`] = `"m1 should be an instance of Matcher, got \\"I am a string\\", it appears that it is no object"`;
exports[`Android generation validation Matcher<View> should fail with a wrong class 1`] = `"m1 should be an instance of Matcher, got \\"[object Object]\\", it appears that it has a wrong class name: \\"AnotherClass\\""`;
Loading

0 comments on commit 6783520

Please sign in to comment.