From 8885da0c988c7d3500251d10d2451693399e5634 Mon Sep 17 00:00:00 2001 From: jos <17252150+jostnes@users.noreply.github.com> Date: Wed, 23 Mar 2022 11:15:08 +0800 Subject: [PATCH 1/7] add waits to fix editor test flakiness --- ...gutenberg-editor-block-insertion-2.test.js | 100 +++--------------- .../__device-tests__/helpers/test-data.js | 24 +++++ .../__device-tests__/pages/editor-page.js | 43 +++++--- 3 files changed, 72 insertions(+), 95 deletions(-) diff --git a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js index 2aefea35ca1c2..ed627957ca2dc 100644 --- a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js +++ b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js @@ -2,22 +2,23 @@ * Internal dependencies */ import { blockNames } from './pages/editor-page'; +import { + headingExpectedHTML, + imageExpectedHTML, + listExpectedHTML, + moreExpectedHTML, + paragraphExpectedHTML, + separatorExpectedHTML, +} from './helpers/test-data'; describe( 'Gutenberg Editor tests for Block insertion 2', () => { it( 'adds new block at the end of post', async () => { await editorPage.addNewBlock( blockNames.heading ); - await editorPage.addNewBlock( blockNames.list ); - const expectedHtml = ` -

- - - - -`; - + const expectedHtml = `${ headingExpectedHTML }\n\n${ listExpectedHTML }`; const html = await editorPage.getHtmlContent(); + expect( html.toLowerCase() ).toBe( expectedHtml ); } ); @@ -27,22 +28,11 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { ); await headingBlockElement.click(); - await editorPage.addNewBlock( blockNames.separator ); - const expectedHtml = ` -

- - - -
- - - - -`; - + const expectedHtml = `${ headingExpectedHTML }\n\n${ separatorExpectedHTML }\n\n${ listExpectedHTML }`; const html = await editorPage.getHtmlContent(); + expect( html.toLowerCase() ).toBe( expectedHtml ); } ); @@ -54,83 +44,27 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { await separatorBlockElement.click(); await editorPage.addNewBlock( blockNames.image, 'before' ); - await editorPage.driver.sleep( 1000 ); await editorPage.closePicker(); - const expectedHtml = ` -

- - - -
- - - -
- - - - -`; - + const expectedHtml = `${ headingExpectedHTML }\n\n${ imageExpectedHTML }\n\n${ separatorExpectedHTML }\n\n${ listExpectedHTML }`; const html = await editorPage.getHtmlContent(); + expect( html.toLowerCase() ).toBe( expectedHtml ); } ); it( 'inserts block at the end of post when no block is selected', async () => { await editorPage.addNewBlock( blockNames.more ); - const expectedHtml = ` -

- - - -
- - - -
- - - - - - - - -`; - + const expectedHtml = `${ headingExpectedHTML }\n\n${ imageExpectedHTML }\n\n${ separatorExpectedHTML }\n\n${ listExpectedHTML }\n\n${ moreExpectedHTML }`; const html = await editorPage.getHtmlContent(); + expect( html.toLowerCase() ).toBe( expectedHtml ); } ); it( 'creates a new Paragraph block tapping on the empty area below the last block', async () => { await editorPage.addParagraphBlockByTappingEmptyAreaBelowLastBlock(); - const expectedHtml = ` -

- - - -
- - - -
- - - - - - - - - - - -

-`; - + const expectedHtml = `${ headingExpectedHTML }\n\n${ imageExpectedHTML }\n\n${ separatorExpectedHTML }\n\n${ listExpectedHTML }\n\n${ moreExpectedHTML }\n\n${ paragraphExpectedHTML }`; const html = await editorPage.getHtmlContent(); expect( html.toLowerCase() ).toBe( expectedHtml ); } ); diff --git a/packages/react-native-editor/__device-tests__/helpers/test-data.js b/packages/react-native-editor/__device-tests__/helpers/test-data.js index d0bcea763a7c0..9c18bdb670055 100644 --- a/packages/react-native-editor/__device-tests__/helpers/test-data.js +++ b/packages/react-native-editor/__device-tests__/helpers/test-data.js @@ -141,3 +141,27 @@ exports.fileBlockPlaceholder = `
`; + +exports.headingExpectedHTML = ` +

+`; + +exports.separatorExpectedHTML = ` +
+`; + +exports.listExpectedHTML = ` + +`; + +exports.imageExpectedHTML = ` +
+`; + +exports.moreExpectedHTML = ` + +`; + +exports.paragraphExpectedHTML = ` +

+`; 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 202f0db13ce1e..c9fa2e50202d4 100644 --- a/packages/react-native-editor/__device-tests__/pages/editor-page.js +++ b/packages/react-native-editor/__device-tests__/pages/editor-page.js @@ -258,22 +258,25 @@ class EditorPage { // ========================= async addNewBlock( blockName, relativePosition ) { - // Click add button. - let identifier = 'Add block'; - if ( isAndroid() ) { - identifier = 'Add block, Double tap to add a block'; - } - const addButton = await this.driver.elementByAccessibilityId( - identifier + const addBlockButtonLocator = isAndroid() + ? '//android.widget.Button[@content-desc="Add block, Double tap to add a block"]' + : '//XCUIElementTypeButton[@name="add-block-button"]'; + + const addButton = await waitForVisible( + this.driver, + addBlockButtonLocator ); if ( relativePosition === 'before' ) { await longPressMiddleOfElement( this.driver, addButton ); + const addBlockBeforeButtonLocator = isAndroid() + ? '//android.widget.Button[@content-desc="Add Block Before"]' + : '//XCUIElementTypeButton[@name="Add Block Before"]'; - const addBlockBeforeButton = await this.driver.elementByAccessibilityId( - 'Add Block Before' + const addBlockBeforeButton = await waitForVisible( + this.driver, + addBlockBeforeButtonLocator ); - await addBlockBeforeButton.click(); } else { await addButton.click(); @@ -281,8 +284,16 @@ class EditorPage { // Click on block of choice. const blockButton = await this.findBlockButton( blockName ); + if ( isAndroid() ) { await blockButton.click(); + + // For certain blocks, clicking on it will display additional options that the test should wait for before next steps + if ( blockName === 'Image' ) { + const locator = + '//android.view.ViewGroup[2]/android.view.ViewGroup/android.view.ViewGroup'; + await waitForVisible( this.driver, locator ); + } } else { await this.driver.execute( 'mobile: tap', { element: blockButton, @@ -299,12 +310,19 @@ class EditorPage { // Attempts to find the given block button in the block inserter control. async findBlockButton( blockName ) { + // Wait for the first block, Paragraph block, to load before looking for other blocks + const paragraphBlockLocator = isAndroid() + ? '//android.widget.Button[@content-desc="Paragraph block"]/android.widget.TextView' + : '//XCUIElementTypeButton[@name="Paragraph block"]'; + + await waitForVisible( this.driver, paragraphBlockLocator ); const blockAccessibilityLabel = `${ blockName } block`; const blockAccessibilityLabelNewBlock = `${ blockAccessibilityLabel }, newly available`; if ( isAndroid() ) { const size = await this.driver.getWindowSize(); const x = size.width / 2; + // Checks if the Block Button is available, and if not will scroll to the second half of the available buttons. while ( ! ( await this.driver.hasElementByAccessibilityId( @@ -613,8 +631,9 @@ class EditorPage { if ( isAndroid() ) { await swipeDown( this.driver ); } else { - const cancelButton = await this.driver.elementByAccessibilityId( - 'Cancel' + const cancelButton = await waitForVisible( + this.driver, + '//XCUIElementTypeButton[@name="Cancel"]' ); await cancelButton.click(); } From dc4337d1cc7ae80f4d5f1d98f392197dde76e74d Mon Sep 17 00:00:00 2001 From: jos <17252150+jostnes@users.noreply.github.com> Date: Wed, 23 Mar 2022 17:53:52 +0800 Subject: [PATCH 2/7] update separator block expected html to latest --- .../react-native-editor/__device-tests__/helpers/test-data.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native-editor/__device-tests__/helpers/test-data.js b/packages/react-native-editor/__device-tests__/helpers/test-data.js index 9c18bdb670055..67ec43f7937cb 100644 --- a/packages/react-native-editor/__device-tests__/helpers/test-data.js +++ b/packages/react-native-editor/__device-tests__/helpers/test-data.js @@ -147,7 +147,7 @@ exports.headingExpectedHTML = ` `; exports.separatorExpectedHTML = ` -
+
`; exports.listExpectedHTML = ` From 1e6fcbc99ef3c15eeb960c065031705474e432e4 Mon Sep 17 00:00:00 2001 From: jos <17252150+jostnes@users.noreply.github.com> Date: Fri, 25 Mar 2022 14:00:49 +0800 Subject: [PATCH 3/7] remove extra spaces --- .../gutenberg-editor-block-insertion-2.test.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js index ed627957ca2dc..f750a0342a443 100644 --- a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js +++ b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js @@ -18,7 +18,6 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { const expectedHtml = `${ headingExpectedHTML }\n\n${ listExpectedHTML }`; const html = await editorPage.getHtmlContent(); - expect( html.toLowerCase() ).toBe( expectedHtml ); } ); @@ -32,7 +31,6 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { const expectedHtml = `${ headingExpectedHTML }\n\n${ separatorExpectedHTML }\n\n${ listExpectedHTML }`; const html = await editorPage.getHtmlContent(); - expect( html.toLowerCase() ).toBe( expectedHtml ); } ); @@ -48,7 +46,6 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { const expectedHtml = `${ headingExpectedHTML }\n\n${ imageExpectedHTML }\n\n${ separatorExpectedHTML }\n\n${ listExpectedHTML }`; const html = await editorPage.getHtmlContent(); - expect( html.toLowerCase() ).toBe( expectedHtml ); } ); @@ -57,7 +54,6 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { const expectedHtml = `${ headingExpectedHTML }\n\n${ imageExpectedHTML }\n\n${ separatorExpectedHTML }\n\n${ listExpectedHTML }\n\n${ moreExpectedHTML }`; const html = await editorPage.getHtmlContent(); - expect( html.toLowerCase() ).toBe( expectedHtml ); } ); From 95417487ac9e266eabeca068d53f45ae03b24870 Mon Sep 17 00:00:00 2001 From: jos <17252150+jostnes@users.noreply.github.com> Date: Mon, 28 Mar 2022 12:36:10 +0800 Subject: [PATCH 4/7] rename test data, move check to different method --- ...gutenberg-editor-block-insertion-2.test.js | 48 ++++++++++++++----- .../__device-tests__/helpers/test-data.js | 12 ++--- .../__device-tests__/pages/editor-page.js | 12 ++--- 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js index f750a0342a443..67754d9458a00 100644 --- a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js +++ b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js @@ -3,12 +3,12 @@ */ import { blockNames } from './pages/editor-page'; import { - headingExpectedHTML, - imageExpectedHTML, - listExpectedHTML, - moreExpectedHTML, - paragraphExpectedHTML, - separatorExpectedHTML, + headerBlockEmpty, + imageBlockEmpty, + listBlockEmpty, + moreBlockEmpty, + paragraphBlockEmpty, + separatorBlockEmpty, } from './helpers/test-data'; describe( 'Gutenberg Editor tests for Block insertion 2', () => { @@ -16,7 +16,7 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { await editorPage.addNewBlock( blockNames.heading ); await editorPage.addNewBlock( blockNames.list ); - const expectedHtml = `${ headingExpectedHTML }\n\n${ listExpectedHTML }`; + const expectedHtml = `${ headerBlockEmpty }\n\n${ listBlockEmpty }`; const html = await editorPage.getHtmlContent(); expect( html.toLowerCase() ).toBe( expectedHtml ); } ); @@ -29,7 +29,12 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { await headingBlockElement.click(); await editorPage.addNewBlock( blockNames.separator ); - const expectedHtml = `${ headingExpectedHTML }\n\n${ separatorExpectedHTML }\n\n${ listExpectedHTML }`; + const expectedHtml = [ + headerBlockEmpty, + separatorBlockEmpty, + listBlockEmpty, + ].join( '\n\n' ); + const html = await editorPage.getHtmlContent(); expect( html.toLowerCase() ).toBe( expectedHtml ); } ); @@ -44,7 +49,13 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { await editorPage.addNewBlock( blockNames.image, 'before' ); await editorPage.closePicker(); - const expectedHtml = `${ headingExpectedHTML }\n\n${ imageExpectedHTML }\n\n${ separatorExpectedHTML }\n\n${ listExpectedHTML }`; + const expectedHtml = [ + headerBlockEmpty, + imageBlockEmpty, + separatorBlockEmpty, + listBlockEmpty, + ].join( '\n\n' ); + const html = await editorPage.getHtmlContent(); expect( html.toLowerCase() ).toBe( expectedHtml ); } ); @@ -52,7 +63,14 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { it( 'inserts block at the end of post when no block is selected', async () => { await editorPage.addNewBlock( blockNames.more ); - const expectedHtml = `${ headingExpectedHTML }\n\n${ imageExpectedHTML }\n\n${ separatorExpectedHTML }\n\n${ listExpectedHTML }\n\n${ moreExpectedHTML }`; + const expectedHtml = [ + headerBlockEmpty, + imageBlockEmpty, + separatorBlockEmpty, + listBlockEmpty, + moreBlockEmpty, + ].join( '\n\n' ); + const html = await editorPage.getHtmlContent(); expect( html.toLowerCase() ).toBe( expectedHtml ); } ); @@ -60,7 +78,15 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { it( 'creates a new Paragraph block tapping on the empty area below the last block', async () => { await editorPage.addParagraphBlockByTappingEmptyAreaBelowLastBlock(); - const expectedHtml = `${ headingExpectedHTML }\n\n${ imageExpectedHTML }\n\n${ separatorExpectedHTML }\n\n${ listExpectedHTML }\n\n${ moreExpectedHTML }\n\n${ paragraphExpectedHTML }`; + const expectedHtml = [ + headerBlockEmpty, + imageBlockEmpty, + separatorBlockEmpty, + listBlockEmpty, + moreBlockEmpty, + paragraphBlockEmpty, + ].join( '\n\n' ); + const html = await editorPage.getHtmlContent(); expect( html.toLowerCase() ).toBe( expectedHtml ); } ); diff --git a/packages/react-native-editor/__device-tests__/helpers/test-data.js b/packages/react-native-editor/__device-tests__/helpers/test-data.js index 67ec43f7937cb..2c851aa195d91 100644 --- a/packages/react-native-editor/__device-tests__/helpers/test-data.js +++ b/packages/react-native-editor/__device-tests__/helpers/test-data.js @@ -142,26 +142,26 @@ exports.audioBlockPlaceholder = `
`; -exports.headingExpectedHTML = ` +exports.headerBlockEmpty = `

`; -exports.separatorExpectedHTML = ` +exports.separatorBlockEmpty = `
`; -exports.listExpectedHTML = ` +exports.listBlockEmpty = ` `; -exports.imageExpectedHTML = ` +exports.imageBlockEmpty = `
`; -exports.moreExpectedHTML = ` +exports.moreBlockEmpty = ` `; -exports.paragraphExpectedHTML = ` +exports.paragraphBlockEmpty = `

`; 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 c9fa2e50202d4..1b00f3a45a603 100644 --- a/packages/react-native-editor/__device-tests__/pages/editor-page.js +++ b/packages/react-native-editor/__device-tests__/pages/editor-page.js @@ -287,13 +287,6 @@ class EditorPage { if ( isAndroid() ) { await blockButton.click(); - - // For certain blocks, clicking on it will display additional options that the test should wait for before next steps - if ( blockName === 'Image' ) { - const locator = - '//android.view.ViewGroup[2]/android.view.ViewGroup/android.view.ViewGroup'; - await waitForVisible( this.driver, locator ); - } } else { await this.driver.execute( 'mobile: tap', { element: blockButton, @@ -322,7 +315,6 @@ class EditorPage { if ( isAndroid() ) { const size = await this.driver.getWindowSize(); const x = size.width / 2; - // Checks if the Block Button is available, and if not will scroll to the second half of the available buttons. while ( ! ( await this.driver.hasElementByAccessibilityId( @@ -629,6 +621,10 @@ class EditorPage { async closePicker() { if ( isAndroid() ) { + // Wait for media block picker to load before closing + const locator = '//android.view.ViewGroup[2]/android.view.ViewGroup/android.view.ViewGroup'; + await waitForVisible( this.driver, locator ); + await swipeDown( this.driver ); } else { const cancelButton = await waitForVisible( From 8fb37dc3830ff4215d1044418940beff04bb6465 Mon Sep 17 00:00:00 2001 From: jos <17252150+jostnes@users.noreply.github.com> Date: Mon, 28 Mar 2022 12:36:54 +0800 Subject: [PATCH 5/7] lint fix --- .../react-native-editor/__device-tests__/pages/editor-page.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 1b00f3a45a603..5486f5b31c327 100644 --- a/packages/react-native-editor/__device-tests__/pages/editor-page.js +++ b/packages/react-native-editor/__device-tests__/pages/editor-page.js @@ -622,7 +622,8 @@ class EditorPage { async closePicker() { if ( isAndroid() ) { // Wait for media block picker to load before closing - const locator = '//android.view.ViewGroup[2]/android.view.ViewGroup/android.view.ViewGroup'; + const locator = + '//android.view.ViewGroup[2]/android.view.ViewGroup/android.view.ViewGroup'; await waitForVisible( this.driver, locator ); await swipeDown( this.driver ); From c1c52960d7421871fbc5b7503f57271db55adf07 Mon Sep 17 00:00:00 2001 From: jos <17252150+jostnes@users.noreply.github.com> Date: Mon, 28 Mar 2022 12:44:29 +0800 Subject: [PATCH 6/7] missed one test data update --- .../gutenberg-editor-block-insertion-2.test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js index 67754d9458a00..c902db3fc45d6 100644 --- a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js +++ b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js @@ -16,7 +16,10 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { await editorPage.addNewBlock( blockNames.heading ); await editorPage.addNewBlock( blockNames.list ); - const expectedHtml = `${ headerBlockEmpty }\n\n${ listBlockEmpty }`; + const expectedHtml = [ + headerBlockEmpty, + listBlockEmpty, + ].join( '\n\n' ); const html = await editorPage.getHtmlContent(); expect( html.toLowerCase() ).toBe( expectedHtml ); } ); From 1b6d50c30715327cb8daedcbc08056cb72189a95 Mon Sep 17 00:00:00 2001 From: jos <17252150+jostnes@users.noreply.github.com> Date: Mon, 28 Mar 2022 12:45:08 +0800 Subject: [PATCH 7/7] lint fix --- .../gutenberg-editor-block-insertion-2.test.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js index c902db3fc45d6..2c6c9bf348118 100644 --- a/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js +++ b/packages/react-native-editor/__device-tests__/gutenberg-editor-block-insertion-2.test.js @@ -16,10 +16,9 @@ describe( 'Gutenberg Editor tests for Block insertion 2', () => { await editorPage.addNewBlock( blockNames.heading ); await editorPage.addNewBlock( blockNames.list ); - const expectedHtml = [ - headerBlockEmpty, - listBlockEmpty, - ].join( '\n\n' ); + const expectedHtml = [ headerBlockEmpty, listBlockEmpty ].join( + '\n\n' + ); const html = await editorPage.getHtmlContent(); expect( html.toLowerCase() ).toBe( expectedHtml ); } );