From 298f7d1bc69d6fc5e1b2efdc1fff7386b2c44585 Mon Sep 17 00:00:00 2001 From: Gerardo Date: Fri, 24 Feb 2023 17:02:37 +0100 Subject: [PATCH] Mobile - E2E helpers: - It adds new waitForElementToBeDisplayedByXPath helper - It adds a new functionality for dismissKeyboard which will handle waiting until the keyboard is fully hidden by taking the initial position of the Add block button in the editor. - It adds setupInitialValues which will handle initial values we want to have available during the tests --- ...erg-editor-block-insertion-@canary.test.js | 4 - .../__device-tests__/pages/editor-page.js | 90 ++++++++++++++----- 2 files changed, 68 insertions(+), 26 deletions(-) diff --git a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-@canary.test.js b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-@canary.test.js index e8f31dcef12161..e5b34078a0e453 100644 --- a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-@canary.test.js +++ b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-@canary.test.js @@ -60,10 +60,6 @@ describe( 'Gutenberg Editor tests for Block insertion', () => { await editorPage.sendTextToParagraphBlock( 1, testData.longText ); // Should have 3 paragraph blocks at this point. - if ( isAndroid() ) { - await editorPage.dismissKeyboard(); - } - const titleElement = await editorPage.getTitleElement( { autoscroll: true, } ); diff --git a/packages/react-native-editor/__device-tests__/pages/editor-page.js b/packages/react-native-editor/__device-tests__/pages/editor-page.js index 7cb432a0c9bb44..6cd79aecf5fade 100644 --- a/packages/react-native-editor/__device-tests__/pages/editor-page.js +++ b/packages/react-native-editor/__device-tests__/pages/editor-page.js @@ -28,7 +28,24 @@ const { const initializeEditorPage = async () => { const driver = await setupDriver(); await isEditorVisible( driver ); - return new EditorPage( driver ); + const initialValues = await setupInitialValues( driver ); + return new EditorPage( driver, initialValues ); +}; + +const ADD_BLOCK_ID = isAndroid() + ? 'Add block, Double tap to add a block' + : 'Add block'; + +// Stores initial values from the editor for different helpers. +const setupInitialValues = async ( driver ) => { + const initialValues = {}; + const addButton = await driver.elementsByAccessibilityId( ADD_BLOCK_ID ); + + if ( addButton.length !== 0 ) { + initialValues.addButtonLocation = await addButton[ 0 ].getLocation(); + } + + return initialValues; }; class EditorPage { @@ -39,10 +56,11 @@ class EditorPage { verseBlockName = 'Verse'; orderedListButtonName = 'Ordered'; - constructor( driver ) { + constructor( driver, initialValues ) { this.driver = driver; this.accessibilityIdKey = 'name'; this.accessibilityIdXPathAttrib = 'name'; + this.initialValues = initialValues; if ( isAndroid() ) { this.accessibilityIdXPathAttrib = 'content-desc'; @@ -54,6 +72,13 @@ class EditorPage { return await this.driver.hasElementByAccessibilityId( 'block-list' ); } + async getAddBlockButton( options = { timeout: 3000 } ) { + return await this.waitForElementToBeDisplayedById( + ADD_BLOCK_ID, + options.timeout + ); + } + // =============================== // Text blocks functions // E.g. Paragraph, Heading blocks @@ -180,12 +205,11 @@ class EditorPage { titleElement ); - if ( - ( elements.length === 0 || ! elements[ 0 ].isDisplayed() ) && - options.autoscroll - ) { - await swipeDown( this.driver ); - return this.getTitleElement( options ); + if ( elements.length === 0 || ! elements[ 0 ].isDisplayed() ) { + if ( options.autoscroll ) { + await swipeDown( this.driver ); + } + return await this.getTitleElement( options ); } return elements[ 0 ]; } @@ -261,18 +285,40 @@ class EditorPage { } async dismissKeyboard() { + const orientation = await this.driver.getOrientation(); const keyboardShown = await this.driver.isKeyboardShown(); if ( ! keyboardShown ) { return; } - if ( isAndroid() ) { + + // On Android with the landspace orientation set, we use the + // driver functionality to hide the keyboard. + if ( isAndroid() && orientation === 'LANDSCAPE' ) { return await this.driver.hideDeviceKeyboard(); } - await clickIfClickable( - this.driver, - '//XCUIElementTypeButton[@name="Hide keyboard"]' - ); + const hideKeyboardButton = isAndroid() + ? await this.waitForElementToBeDisplayedById( + 'Hide keyboard, Tap to hide the keyboard' + ) + : await this.waitForElementToBeDisplayedByXPath( + '//XCUIElementTypeButton[@name="Hide keyboard"]' + ); + + await hideKeyboardButton.click(); + await this.waitForKeyboardToBeHidden(); + } + + // Takes the add block button as reference for the keyboard to be + // fully hidden. + async waitForKeyboardToBeHidden() { + const { addButtonLocation } = this.initialValues; + const addButton = await this.getAddBlockButton(); + const location = await addButton.getLocation(); + + if ( location.y < addButtonLocation?.y ) { + await this.waitForKeyboardToBeHidden(); + } } async dismissAndroidClipboardSmartSuggestion() { @@ -324,13 +370,7 @@ class EditorPage { // ========================= async addNewBlock( blockName, relativePosition ) { - const addBlockElement = isAndroid() - ? 'Add block, Double tap to add a block' - : 'Add block'; - const addButton = await this.waitForElementToBeDisplayedById( - addBlockElement, - 3000 - ); + const addButton = await this.getAddBlockButton(); if ( relativePosition === 'before' ) { // On Android it doesn't get the right size of the button @@ -843,13 +883,19 @@ class EditorPage { } async waitForElementToBeDisplayedById( id, timeout = 2000 ) { - await this.driver.waitForElementByAccessibilityId( + return await this.driver.waitForElementByAccessibilityId( id, wd.asserters.isDisplayed, timeout ); + } - return await this.driver.elementByAccessibilityId( id ); + async waitForElementToBeDisplayedByXPath( id, timeout = 2000 ) { + return await this.driver.waitForElementByXPath( + id, + wd.asserters.isDisplayed, + timeout + ); } }