-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Can swipe and tap on screenshot #260
Changes from 10 commits
e0061ec
79345ad
7384776
18480fd
be0a0a7
61cfc83
18baeb6
35dd72e
e66eb29
11c794b
0e9ad30
de77ceb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import Bluebird from 'bluebird'; | ||
import _ from 'lodash'; | ||
import wd from 'wd'; | ||
|
||
export default class AppiumMethodHandler { | ||
constructor (driver) { | ||
|
@@ -80,7 +81,14 @@ export default class AppiumMethodHandler { | |
|
||
async executeMethod (methodName, args = []) { | ||
let res = {}; | ||
if (methodName !== 'source' && methodName !== 'screenshot') { | ||
|
||
// Specially handle the tap method | ||
if (methodName === 'tap') { | ||
res = await (new wd.TouchAction(this.driver)).tap({x: args[0], y: args[1]}).perform(); | ||
} else if (methodName === 'swipe') { | ||
const [startX, startY, endX, endY] = args; | ||
res = await (new wd.TouchAction(this.driver)).press({x: startX, y: startY}).moveTo({x: endX, y: endY}).release().perform(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think this would look cleaner separating out the individual commands on separate lines: res = await (new wd.TouchAction(this.driver))
.press({x: startX, y: starty})
.moveTo({x: endX, y: endY})
.release()
.perform(); |
||
} else if (methodName !== 'source' && methodName !== 'screenshot') { | ||
res = await this.driver[methodName].apply(this.driver, args); | ||
} | ||
|
||
|
@@ -94,7 +102,7 @@ export default class AppiumMethodHandler { | |
res, | ||
}; | ||
} | ||
|
||
async _getSourceAndScreenshot () { | ||
let source, sourceError, screenshot, screenshotError; | ||
try { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ import { debounce } from 'lodash'; | |
import HighlighterRect from './HighlighterRect'; | ||
import Actions from './Actions'; | ||
import { Spin } from 'antd'; | ||
import B from 'bluebird'; | ||
import styles from './Inspector.css'; | ||
import { parseCoordinates } from './shared'; | ||
|
||
|
@@ -35,15 +36,61 @@ export default class Screenshot extends Component { | |
|
||
} | ||
|
||
handleScreenshotClick (e) { | ||
const {screenshotInteractionMode} = this.props; | ||
async handleScreenshotClick () { | ||
const {screenshotInteractionMode, applyClientMethod, | ||
swipeStart, swipeEnd, setSwipeStart, setSwipeEnd} = this.props; | ||
const {x, y} = this.state; | ||
|
||
if (screenshotInteractionMode === 'tap') { | ||
applyClientMethod({ | ||
methodName: 'tap', | ||
args: [x, y], | ||
}); | ||
} else if (screenshotInteractionMode === 'swipe') { | ||
if (!swipeStart) { | ||
setSwipeStart(x, y); | ||
} else if (!swipeEnd) { | ||
setSwipeEnd(x, y); | ||
await B.delay(500); // Wait a second to do the swipe so user can see the SVG line | ||
await this.handleDoSwipe(); | ||
} | ||
} | ||
} | ||
|
||
handleMouseMove (e) { | ||
const {screenshotInteractionMode} = this.props; | ||
const {scaleRatio} = this.state; | ||
|
||
if (screenshotInteractionMode !== 'select') { | ||
const offsetX = e.nativeEvent.offsetX; | ||
const offsetY = e.nativeEvent.offsetY; | ||
console.log('!!!!', offsetX, offsetY); | ||
const x = offsetX * scaleRatio; | ||
const y = offsetY * scaleRatio; | ||
this.setState({ | ||
...this.state, | ||
x: Math.round(x), | ||
y: Math.round(y), | ||
}); | ||
} | ||
} | ||
|
||
handleMouseOut () { | ||
this.setState({ | ||
...this.state, | ||
x: undefined, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i don't like setting things to undefined, can we do |
||
y: undefined, | ||
}); | ||
} | ||
|
||
async handleDoSwipe () { | ||
const {swipeStart, swipeEnd, clearSwipeAction, applyClientMethod} = this.props; | ||
await applyClientMethod({ | ||
methodName: 'swipe', | ||
args: [swipeStart.x, swipeStart.y, swipeEnd.x - swipeStart.x, swipeEnd.y - swipeStart.y], | ||
}); | ||
clearSwipeAction(); | ||
} | ||
|
||
componentDidMount () { | ||
// When DOM is ready, calculate the image scale ratio and re-calculate it whenever the window is resized | ||
this.updateScaleRatio(); | ||
|
@@ -55,8 +102,9 @@ export default class Screenshot extends Component { | |
} | ||
|
||
render () { | ||
const {source, screenshot, methodCallInProgress, screenshotInteractionMode} = this.props; | ||
const {scaleRatio} = this.state; | ||
const {source, screenshot, methodCallInProgress, screenshotInteractionMode, | ||
swipeStart, swipeEnd, clearSwipeAction} = this.props; | ||
const {scaleRatio, x, y} = this.state; | ||
|
||
// Recurse through the 'source' JSON and render a highlighter rect for each element | ||
const highlighterRects = []; | ||
|
@@ -89,20 +137,48 @@ export default class Screenshot extends Component { | |
// If we're tapping or swiping, show the 'touch' cursor style | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the comment here doesn't seem to match what we're doing |
||
const screenshotStyle = {}; | ||
if (screenshotInteractionMode === 'tap' || screenshotInteractionMode === 'swipe') { | ||
screenshotStyle.cursor = 'crosshair'; // TODO: Change this to touch | ||
screenshotStyle.cursor = 'crosshair'; | ||
} | ||
|
||
recursive(source); | ||
|
||
// Show the screenshot and highlighter rects. Show loading indicator if a method call is in progress. | ||
return <Spin size='large' spinning={!!methodCallInProgress}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there is now enough HTML code here I wonder if we should factor out some smaller components. up to you. |
||
<Actions {...this.props} /> | ||
<div ref={(containerEl) => { this.containerEl = containerEl; }} | ||
style={screenshotStyle} | ||
onClick={this.handleScreenshotClick.bind(this)} | ||
className={styles.screenshotBox}> | ||
<img src={`data:image/gif;base64,${screenshot}`} id="screenshot" /> | ||
{screenshotInteractionMode === 'select' && highlighterRects} | ||
<div className={styles.innerScreenshotContainer}> | ||
<div className={styles.screenshotActionsPanel}> | ||
<Actions {...this.props} /> | ||
</div> | ||
<div ref={(containerEl) => { this.containerEl = containerEl; }} | ||
style={screenshotStyle} | ||
onClick={this.handleScreenshotClick.bind(this)} | ||
onMouseMove={this.handleMouseMove.bind(this)} | ||
onMouseOut={this.handleMouseOut.bind(this)} | ||
className={styles.screenshotBox}> | ||
{x !== undefined ? <div className={styles.coordinatesContainer}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this check could then be a more natural null check |
||
<p>X: {x}</p> | ||
<p>Y: {y}</p> | ||
</div> : null} | ||
<img src={`data:image/gif;base64,${screenshot}`} id="screenshot" /> | ||
{screenshotInteractionMode === 'select' && highlighterRects} | ||
{screenshotInteractionMode === 'swipe' && <div> | ||
{(!swipeStart || !swipeEnd) && <div className={styles.swipeInstructions}> | ||
{!swipeStart && <p>Click swipe start</p>} | ||
{swipeStart && !swipeEnd && <p>Click swipe end</p>} | ||
</div>} | ||
<svg className={styles.swipeSvg}> | ||
{swipeStart && !swipeEnd && <circle | ||
cx={swipeStart.x / scaleRatio} | ||
cy={swipeStart.y / scaleRatio} | ||
/>} | ||
{swipeStart && swipeEnd && <line | ||
x1={swipeStart.x / scaleRatio} | ||
y1={swipeStart.y / scaleRatio} | ||
x2={swipeEnd.x / scaleRatio} | ||
y2={swipeEnd.y / scaleRatio} | ||
/>} | ||
</svg> | ||
</div>} | ||
</div> | ||
</div> | ||
</Spin>; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,6 +97,14 @@ ${this.indent(code, 4)} | |
codeFor_back () { | ||
return `driver.navigate().back();`; | ||
} | ||
|
||
codeFor_tap (varNameIgnore, varIndexIgnore, x, y) { | ||
return `(new TouchAction(driver)).tap(${x}, ${y}).perform()`; | ||
} | ||
|
||
codeFor_swipe (varNameIgnore, varIndexIgnore, x1, y1, x2, y2) { | ||
return `(new TouchAction(driver)).press({x: ${x1}, y: ${y1}}).moveTo({x: ${x2}: y: ${y2}}).release().perform()`; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think we should also split this onto multiple lines and indent for the generated code as well. |
||
} | ||
} | ||
|
||
JavaFramework.readableName = "Java - JUnit"; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aren't we specially handling the tap and swipe methods here?