-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
UI Tests for Block Mover #27883
UI Tests for Block Mover #27883
Changes from all commits
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 |
---|---|---|
@@ -0,0 +1,158 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import { isAndroid } from './helpers/utils'; | ||
import { blockNames } from './pages/editor-page'; | ||
|
||
describe( 'Gutenberg Editor Block Mover tests', () => { | ||
const cancelButtonName = 'Cancel'; | ||
const buttonIosType = 'Button'; | ||
const moveTopButtonName = 'Move to top'; | ||
const moveBottomButtonName = 'Move to bottom'; | ||
|
||
async function setupBlocks( text = 'p1' ) { | ||
await editorPage.addNewBlock( blockNames.paragraph ); | ||
const paragraphBlock = await editorPage.getBlockAtPosition( | ||
blockNames.paragraph | ||
); | ||
await editorPage.typeTextToParagraphBlock( paragraphBlock, text ); | ||
|
||
await editorPage.addNewBlock( blockNames.heading ); | ||
const headerBlock = await editorPage.getBlockAtPosition( | ||
blockNames.heading, | ||
2 | ||
); | ||
await editorPage.typeTextToParagraphBlock( headerBlock, text ); | ||
} | ||
|
||
async function removeBlocks( blockOrder ) { | ||
for ( let i = blockOrder.length; i > 0; i-- ) { | ||
await editorPage.removeBlockAtPosition( blockOrder[ i - 1 ], i ); | ||
} | ||
} | ||
|
||
async function cancelActionSheet( ePage ) { | ||
if ( isAndroid() ) { | ||
await ePage.tapCoordinates( 100, 100 ); | ||
} else { | ||
await ePage.selectElement( cancelButtonName, buttonIosType ); | ||
} | ||
} | ||
|
||
it( 'should be able to see move block to top when long pressing up and change nothing when pressing cancel', async () => { | ||
await setupBlocks( 'p1-up-cancel' ); | ||
|
||
await editorPage.longPressToolBarButton( | ||
'Move block up from row 2 to row 1' | ||
); | ||
const moveUpAction = await editorPage.findElementByXPath( | ||
moveTopButtonName, | ||
buttonIosType | ||
); | ||
|
||
expect( moveUpAction ).toBeTruthy(); | ||
|
||
await cancelActionSheet( editorPage ); | ||
const paragraphIsFirst = await editorPage.hasBlockAtPosition( | ||
1, | ||
blockNames.paragraph | ||
); | ||
|
||
expect( paragraphIsFirst ).toBe( true ); | ||
|
||
await removeBlocks( [ blockNames.paragraph, blockNames.heading ] ); | ||
} ); | ||
|
||
it( 'should be able to move block to first block when pressing move block to top', async () => { | ||
await setupBlocks( 'p1-up' ); | ||
|
||
await editorPage.longPressToolBarButton( | ||
'Move block up from row 2 to row 1' | ||
); | ||
await editorPage.selectElement( moveTopButtonName, buttonIosType ); | ||
const headerIsFirst = await editorPage.hasBlockAtPosition( | ||
1, | ||
blockNames.heading | ||
); | ||
|
||
expect( headerIsFirst ).toBe( true ); | ||
|
||
await editorPage.selectBlock( blockNames.paragraph, 2 ); | ||
await removeBlocks( [ blockNames.heading, blockNames.paragraph ] ); | ||
} ); | ||
|
||
it( 'should have move up disabled when on top', async () => { | ||
await setupBlocks( 'p1-disabled-top' ); | ||
await editorPage.selectBlock( blockNames.paragraph ); | ||
|
||
await editorPage.longPressToolBarButton( 'Move block up' ); | ||
const moveUpAction = await editorPage.findElementByXPath( | ||
moveTopButtonName, | ||
buttonIosType | ||
); | ||
|
||
expect( moveUpAction ).toBe( undefined ); | ||
|
||
await editorPage.selectBlock( blockNames.heading, 2 ); | ||
await removeBlocks( [ blockNames.paragraph, blockNames.heading ] ); | ||
} ); | ||
|
||
it( 'should be able to see move block to bottom when long pressing down and change nothing when pressing cancel', async () => { | ||
await setupBlocks( 'p1-down-cancel' ); | ||
await editorPage.selectBlock( blockNames.paragraph ); | ||
|
||
await editorPage.longPressToolBarButton( | ||
'Move block down from row 1 to row 2' | ||
); | ||
const moveDownAction = await editorPage.findElementByXPath( | ||
moveBottomButtonName, | ||
buttonIosType | ||
); | ||
|
||
expect( moveDownAction ).toBeTruthy(); | ||
|
||
await cancelActionSheet( editorPage ); | ||
const paragraphIsFirst = await editorPage.hasBlockAtPosition( | ||
1, | ||
blockNames.paragraph | ||
); | ||
|
||
expect( paragraphIsFirst ).toBe( true ); | ||
|
||
await editorPage.selectBlock( blockNames.heading, 2 ); | ||
await removeBlocks( [ blockNames.paragraph, blockNames.heading ] ); | ||
} ); | ||
|
||
it( 'should be able to move block to last block when pressing move block to bottom', async () => { | ||
await setupBlocks( 'p1-down' ); | ||
await editorPage.selectBlock( blockNames.paragraph ); | ||
|
||
await editorPage.longPressToolBarButton( | ||
'Move block down from row 1 to row 2' | ||
); | ||
|
||
await editorPage.selectElement( moveBottomButtonName, buttonIosType ); | ||
const headerIsFirst = await editorPage.hasBlockAtPosition( | ||
1, | ||
blockNames.heading | ||
); | ||
|
||
expect( headerIsFirst ).toBe( true ); | ||
|
||
await removeBlocks( [ blockNames.heading, blockNames.paragraph ] ); | ||
} ); | ||
|
||
it( 'should have move down disabled when on bottom', async () => { | ||
await setupBlocks( 'p1-disabled-down' ); | ||
|
||
await editorPage.longPressToolBarButton( 'Move block down' ); | ||
const moveDownAction = await editorPage.findElementByXPath( | ||
moveBottomButtonName, | ||
buttonIosType | ||
); | ||
|
||
expect( moveDownAction ).toBe( undefined ); | ||
|
||
await removeBlocks( [ blockNames.paragraph, blockNames.heading ] ); | ||
} ); | ||
} ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,14 +5,20 @@ const { | |
setupDriver, | ||
stopDriver, | ||
isAndroid, | ||
longPressMiddleOfElement, | ||
swipeUp, | ||
swipeDown, | ||
typeString, | ||
toggleHtmlMode, | ||
swipeFromTo, | ||
longPressMiddleOfElement, | ||
} = require( '../helpers/utils' ); | ||
|
||
/** | ||
* External dependencies | ||
*/ | ||
// eslint-disable-next-line import/no-extraneous-dependencies | ||
const wd = require( 'wd' ); | ||
|
||
const initializeEditorPage = async () => { | ||
const driver = await setupDriver(); | ||
return new EditorPage( driver ); | ||
|
@@ -288,6 +294,20 @@ class EditorPage { | |
await toolBarButton.click(); | ||
} | ||
|
||
async longPressToolBarButton( buttonName ) { | ||
let toolBarButton; | ||
if ( isAndroid() ) { | ||
const blockLocator = `//*[contains(@${ this.accessibilityIdXPathAttrib }, "${ buttonName }")]`; | ||
toolBarButton = await this.driver.elementByXPath( blockLocator ); | ||
} else { | ||
toolBarButton = await this.driver.elementByAccessibilityId( | ||
buttonName | ||
); | ||
} | ||
|
||
await longPressMiddleOfElement( this.driver, toolBarButton ); | ||
} | ||
|
||
// ========================= | ||
// Inline toolbar functions | ||
// ========================= | ||
|
@@ -384,11 +404,15 @@ class EditorPage { | |
} | ||
|
||
async typeTextToParagraphBlock( block, text, clear ) { | ||
const textViewElement = await this.getTextViewForParagraphBlock( | ||
block | ||
); | ||
await typeString( this.driver, textViewElement, text, clear ); | ||
await this.driver.sleep( 1000 ); // Give time for the block to rerender (such as for accessibility) | ||
if ( ! isAndroid() ) { | ||
block.type( text ); | ||
} else { | ||
const textViewElement = await this.getTextViewForParagraphBlock( | ||
block | ||
); | ||
await typeString( this.driver, textViewElement, text, clear ); | ||
await this.driver.sleep( 1000 ); // Give time for the block to rerender (such as for accessibility) | ||
} | ||
} | ||
|
||
async sendTextToParagraphBlock( position, text, clear ) { | ||
|
@@ -572,6 +596,46 @@ class EditorPage { | |
async sauceJobStatus( allPassed ) { | ||
await this.driver.sauceJobStatus( allPassed ); | ||
} | ||
|
||
// ============================= | ||
// Misc functions | ||
// ============================= | ||
async findElementByXPath( name, iosElementType ) { | ||
const elementName = isAndroid() | ||
? '//*' | ||
: `//XCUIElementType${ iosElementType }`; | ||
const blockLocator = `${ elementName }[contains(@${ this.accessibilityIdXPathAttrib }, "${ name }")]`; | ||
const elements = await this.driver.elementsByXPath( blockLocator ); | ||
return elements[ 0 ]; | ||
} | ||
|
||
async selectElement( name, iosElementType ) { | ||
const el = await this.findElementByXPath( name, iosElementType ); | ||
el.click(); | ||
} | ||
|
||
async selectBlock( | ||
blockName, | ||
position = 1, | ||
options = { autoscroll: false } | ||
) { | ||
const block = await this.getBlockAtPosition( | ||
blockName, | ||
position, | ||
options | ||
); | ||
block.click(); | ||
} | ||
|
||
async tapCoordinates( x, y, longPress = false ) { | ||
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. If possible, using 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. Hmmm. The problem is that I need to click outside of the alert and I can't get elements behind the alert. 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. Would pressing the back button instead on Android work? |
||
const action = new wd.TouchAction( this.driver ); | ||
action.press( { x, y } ); | ||
if ( longPress ) { | ||
action.wait( 1000 ); | ||
} | ||
action.release(); | ||
await action.perform(); | ||
} | ||
} | ||
|
||
const blockNames = { | ||
|
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.
This seemed to be the failure reason for some of the e2e tests. What was the reason behind this change?
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.
I changed this because locally my machine wouldn't type anything on iOS with that function. Not sure if I have something set up wrong?
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.
Which iOS simulator (version, device) were you using?