-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add paragraph block writing flow tests #821
Changes from 57 commits
6d1b407
be25642
0f52256
c7eec61
284ecde
9bce282
188436c
4654a26
f1ccfd2
fbc6fe9
97588dc
9757529
212df48
9441c7b
f05d9c9
eed3b95
cc8e999
4272d85
7a557de
b669430
7f9e48e
c227250
72928aa
0856bac
60d5970
28ba568
013fe27
6b5441f
dff6090
aea1257
26769c1
1d8e18f
5c69b1a
8e1849c
f0cd38d
5c896f4
89d61fc
a67a5c7
be18d5f
c866ee5
478c8a7
2a06e92
8278d49
76d7e94
3a9966f
73c406f
ffd57d1
94e5b05
243385d
d0e56b2
f303bc0
d65b6fa
60b3d06
af3bc23
ca0a861
f0a5ccc
2bde312
48b46a9
dfe8851
85fc10e
14977c1
83c779d
036a28c
ba18700
41adacc
7acefbc
548f324
a74af6a
fabc73c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
exports.shortText = `Hello Gutenberg! My name is Appium`; | ||
|
||
exports.longText = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam luctus velit et nunc tristique, ut tincidunt ipsum placerat. Maecenas placerat nec elit sit amet vulputate. | ||
Nam suscipit dolor eu arcu efficitur, nec faucibus sapien ullamcorper. Etiam nibh risus, tincidunt quis purus a, dictum porta dui. Phasellus lacinia iaculis odio, et eleifend d | ||
Nullam suscipit volutpat velit eget varius. Etiam diam ex, finibus eu turpis a, semper tempus ante. Vestibulum quis elit et felis sagittis mollis. | ||
Nullam porta aliquam nisi, eu dapibus mauris dignissim at. Praesent ut congue sem. Nullam a rhoncus metus.`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,13 @@ const localIOSAppPath = process.env.IOS_APP_PATH || defaultIOSAppPath; | |
const localAppiumPort = serverConfigs.local.port; // Port to spawn appium process for local runs | ||
let appiumProcess: ?childProcess.ChildProcess; | ||
|
||
// Used to map unicode and special values to keycodes on Android | ||
// Docs for keycode values: https://developer.android.com/reference/android/view/KeyEvent.html | ||
const strToKeycode = { | ||
'\n': 66, | ||
'\u0008': 67, | ||
}; | ||
|
||
const timer = ( ms: number ) => new Promise < {} > ( ( res ) => setTimeout( res, ms ) ); | ||
|
||
const isAndroid = () => { | ||
|
@@ -92,8 +99,9 @@ const setupDriver = async () => { | |
} | ||
|
||
if ( ! isLocalEnvironment() ) { | ||
desiredCaps.name = `Gutenberg Editor Tests[${ rnPlatform }]`; | ||
desiredCaps.tags = [ 'Gutenberg' ]; | ||
const branch = process.env.CIRCLE_BRANCH || ''; | ||
desiredCaps.name = `Gutenberg Editor Tests[${ rnPlatform }]-${ branch }`; | ||
desiredCaps.tags = [ 'Gutenberg', branch ]; | ||
} | ||
|
||
await driver.init( desiredCaps ); | ||
|
@@ -129,10 +137,86 @@ const stopDriver = async ( driver: wd.PromiseChainWebdriver ) => { | |
} | ||
}; | ||
|
||
// attempts to type a string to a given element, need for this stems from | ||
// https://github.com/appium/appium/issues/12285#issuecomment-471872239 | ||
// https://github.com/facebook/WebDriverAgent/issues/1084 | ||
const typeString = async ( driver: wd.PromiseChainWebdriver, element: wd.PromiseChainWebdriver.Element, str: string, clear: boolean = false ) => { | ||
if ( clear ) { | ||
await element.clear(); | ||
} | ||
|
||
if ( isAndroid() ) { | ||
const paragraphs = str.split( '\n' ); | ||
|
||
for ( let i = 0; i < paragraphs.length; i++ ) { | ||
const paragraph = paragraphs[ i ].replace( /[ ]/g, '%s' ); | ||
if ( paragraph in strToKeycode ) { | ||
await driver.pressKeycode( strToKeycode[ paragraph ] ); | ||
} else { | ||
// Execute with adb shell input <text> since normal type auto clears field on Android | ||
await driver.execute( 'mobile: shell', { command: 'input', args: [ 'text', paragraph ] } ); | ||
} | ||
if ( i !== paragraphs.length - 1 ) { | ||
await driver.pressKeycode( strToKeycode[ '\n' ] ); | ||
} | ||
} | ||
} else { | ||
return await element.type( str ); | ||
} | ||
}; | ||
|
||
// Calculates middle x,y and clicks that position | ||
const clickMiddleOfElement = async ( driver: wd.PromiseChainWebdriver, element: wd.PromiseChainWebdriver.Element ) => { | ||
const location = await element.getLocation(); | ||
const size = await element.getSize(); | ||
|
||
const action = await new wd.TouchAction( driver ); | ||
action.press( { x: location.x + ( size.width / 2 ), y: location.y } ); | ||
action.release(); | ||
await action.perform(); | ||
}; | ||
|
||
// Clicks in the top left of an element | ||
const clickBeginningOfElement = async ( driver: wd.PromiseChainWebdriver, element: wd.PromiseChainWebdriver.Element ) => { | ||
const location = await element.getLocation(); | ||
const action = await new wd.TouchAction( driver ); | ||
action.press( { x: location.x, y: location.y } ); | ||
action.release(); | ||
await action.perform(); | ||
}; | ||
|
||
// Starts from the middle of the screen or the element(if specified) | ||
// and swipes upwards | ||
const swipeUp = async ( driver: wd.PromiseChainWebdriver, element: wd.PromiseChainWebdriver.Element = undefined ) => { | ||
let size = await driver.getWindowSize(); | ||
let y = 0; | ||
if ( element !== undefined ) { | ||
size = await element.getSize(); | ||
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 feel this function could use an upgrade (maybe in another PR?) It seems to me that there are quite few edge cases where this approach would fail:
I think a "slightly" better approach would be to make this function a simple swipe up with an height parameter, it will try to center the swipe on the screen and do it in a loop if height is bigger than the size of the screen. We can also think of a 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. For sure! I was saving improving this for another PR, do you think it's good enough for now?
It originally just did this, but failed on the CI because the device it used was small and the keyboard took up more than half of the screen.
Yep, for now I was hoping this was enough to use in a loop if needed before that get's implemented. 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 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. Yep it seems to work really smoothly for now (at least on the devices we tested :)). So I think we should be good 👍 |
||
const location = await element.getLocation(); | ||
y = location.y; | ||
} | ||
|
||
const startX = size.width / 2; | ||
const startY = y + ( size.height / 3 ); | ||
const endX = startX; | ||
const endY = startY + ( startY * -1 * 0.5 ); | ||
|
||
const action = await new wd.TouchAction( driver ); | ||
action.press( { x: startX, y: startY } ); | ||
action.wait( 3000 ); | ||
action.moveTo( { x: endX, y: endY } ); | ||
action.release(); | ||
await action.perform(); | ||
}; | ||
|
||
module.exports = { | ||
timer, | ||
setupDriver, | ||
isLocalEnvironment, | ||
isAndroid, | ||
typeString, | ||
clickMiddleOfElement, | ||
clickBeginningOfElement, | ||
swipeUp, | ||
stopDriver, | ||
}; |
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.
The need for this additional work for Android is because of how the type API works. It basically clears the field first before start typing. Although Appium implemented a workaround in their additional implementation on top of this to allow appending by copying the existing text before typing the new one, unfortunately, it still performs the 'clear' operation under the hood. Because of that when it clears it, it doesn't know when to stop properly and removes the block, as if the user had touched the backspace button on an empty block.
The workaround uses
adb shell input <text>
instead to send the text.