From 82de3b63811a35ae9f56f3bb1018bbffddeef41f Mon Sep 17 00:00:00 2001 From: Matthew Kevins Date: Sat, 15 Jun 2019 08:02:01 +1000 Subject: [PATCH] Fix Android device tests for AndroidX migration (#1125) * Proxy driver to patch accessibilityId function calls on Android * Remove geolocation from project as it's depricated --- __device-tests__/helpers/utils.js | 23 ++++++++++++++++-- __device-tests__/pages/editor-page.js | 27 +++++++++++++++------ ios/gutenberg.xcodeproj/project.pbxproj | 31 +------------------------ 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/__device-tests__/helpers/utils.js b/__device-tests__/helpers/utils.js index a076441434..cc63feeb69 100644 --- a/__device-tests__/helpers/utils.js +++ b/__device-tests__/helpers/utils.js @@ -114,9 +114,28 @@ const setupDriver = async () => { await driver.setImplicitWaitTimeout( 2000 ); await timer( 3000 ); - await driver.setOrientation( 'PORTRAIT' ); - return driver; + + // Proxy driver to patch functions on Android + // This is needed to adapt to changes in the way accessibility ids are being + // assigned after migrating to AndroidX and React Native 0.60. See: + // https://github.com/wordpress-mobile/gutenberg-mobile/pull/1112#issuecomment-501165250 + // for more details. + return new Proxy( driver, { + get: ( original, property ) => { + const propertiesToPatch = [ + 'elementByAccessibilityId', + 'hasElementByAccessibilityId', + ]; + if ( isAndroid() && ( propertiesToPatch.includes( property ) ) ) { + return async function( value, cb ) { + // Add a comma and a space to all ids + return await original[ property ]( `${ value }, `, cb ); + }; + } + return original[ property ]; + }, + } ); }; const stopDriver = async ( driver: wd.PromiseChainWebdriver ) => { diff --git a/__device-tests__/pages/editor-page.js b/__device-tests__/pages/editor-page.js index 7fb7c1f826..d63ba54f65 100644 --- a/__device-tests__/pages/editor-page.js +++ b/__device-tests__/pages/editor-page.js @@ -19,6 +19,12 @@ export default class EditorPage { paragraphBlockName = 'Paragraph'; listBlockName = 'List'; + // This is needed to adapt to changes in the way accessibility ids are being + // assigned after migrating to AndroidX and React Native 0.60. See: + // https://github.com/wordpress-mobile/gutenberg-mobile/pull/1112#issuecomment-501165250 + // for more details. + accessibilityIdSuffix = ''; + constructor( driver: wd.PromiseChainWebdriver ) { this.driver = driver; this.accessibilityIdKey = 'name'; @@ -27,6 +33,7 @@ export default class EditorPage { if ( isAndroid() ) { this.accessibilityIdXPathAttrib = 'content-desc'; this.accessibilityIdKey = 'contentDescription'; + this.accessibilityIdSuffix = ', '; } } @@ -48,7 +55,7 @@ export default class EditorPage { } async getTextViewForHtmlViewContent() { - const accessibilityId = 'html-view-content'; + const accessibilityId = `html-view-content${ this.accessibilityIdSuffix }`; let blockLocator = `//*[@${ this.accessibilityIdXPathAttrib }="${ accessibilityId }"]`; if ( ! isAndroid() ) { @@ -106,11 +113,13 @@ export default class EditorPage { if ( ! await this.hasBlockAtPosition( position, blockName ) ) { throw Error( `No Block at position ${ position }` ); } + const parentId = `${ blockName } Block. Row ${ position }.${ this.accessibilityIdSuffix }`; + const parentLocator = `//*[@${ this.accessibilityIdXPathAttrib }="${ parentId }"]`; - const parentLocator = `//*[@${ this.accessibilityIdXPathAttrib }="${ blockName } Block. Row ${ position }."]`; + const blockId = `Move block up from row ${ position } to row ${ position - 1 }${ this.accessibilityIdSuffix }`; let blockLocator = `${ parentLocator }/following-sibling::*`; blockLocator += isAndroid() ? '' : '//*'; - blockLocator += `[@${ this.accessibilityIdXPathAttrib }="Move block up from row ${ position } to row ${ position - 1 }"]`; + blockLocator += `[@${ this.accessibilityIdXPathAttrib }="${ blockId }"]`; const moveUpButton = await this.driver.elementByXPath( blockLocator ); await moveUpButton.click(); } @@ -121,10 +130,13 @@ export default class EditorPage { throw Error( `No Block at position ${ position }` ); } - const parentLocator = `//*[contains(@${ this.accessibilityIdXPathAttrib }, "${ blockName } Block. Row ${ position }.")]`; + const parentId = `${ blockName } Block. Row ${ position }.`; + const parentLocator = `//*[contains(@${ this.accessibilityIdXPathAttrib }, "${ parentId }")]`; + + const blockId = `Move block down from row ${ position } to row ${ position + 1 }${ this.accessibilityIdSuffix }`; let blockLocator = `${ parentLocator }/following-sibling::*`; blockLocator += isAndroid() ? '' : '//*'; - blockLocator += `[@${ this.accessibilityIdXPathAttrib }="Move block down from row ${ position } to row ${ position + 1 }"]`; + blockLocator += `[@${ this.accessibilityIdXPathAttrib }="${ blockId }"]`; const moveDownButton = await this.driver.elementByXPath( blockLocator ); await moveDownButton.click(); } @@ -136,13 +148,14 @@ export default class EditorPage { throw Error( `No Block at position ${ position }` ); } - const parentLocator = `//*[contains(@${ this.accessibilityIdXPathAttrib }, "${ blockName } Block. Row ${ position }.")]`; + const parentId = `${ blockName } Block. Row ${ position }.`; + const parentLocator = `//*[contains(@${ this.accessibilityIdXPathAttrib }, "${ parentId }")]`; let removeBlockLocator = `${ parentLocator }/following-sibling::*`; removeBlockLocator += isAndroid() ? '' : '//*'; let removeButtonIdentifier = `Remove block at row ${ position }`; if ( isAndroid() ) { - removeButtonIdentifier += ', Double tap to remove the block'; + removeButtonIdentifier += `, Double tap to remove the block${ this.accessibilityIdSuffix }`; const block = await this.getBlockAtPosition( position, blockName ); let checkList = await this.driver.elementsByXPath( removeBlockLocator ); while ( checkList.length === 0 ) { diff --git a/ios/gutenberg.xcodeproj/project.pbxproj b/ios/gutenberg.xcodeproj/project.pbxproj index 81f5ba50a1..7de2eeb274 100644 --- a/ios/gutenberg.xcodeproj/project.pbxproj +++ b/ios/gutenberg.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; - 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; @@ -64,13 +63,6 @@ remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTActionSheet; }; - 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RCTGeolocation; - }; 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; @@ -411,7 +403,6 @@ /* Begin PBXFileReference section */ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; - 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; @@ -481,7 +472,6 @@ 146834051AC3E58100842450 /* libReact.a in Frameworks */, 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */, 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, - 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */, 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, @@ -533,14 +523,6 @@ name = Products; sourceTree = ""; }; - 00C302B61ABCB90400DB3ED1 /* Products */ = { - isa = PBXGroup; - children = ( - 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */, - ); - name = Products; - sourceTree = ""; - }; 00C302BC1ABCB91800DB3ED1 /* Products */ = { isa = PBXGroup; children = ( @@ -693,7 +675,6 @@ 146833FF1AC3E56700842450 /* React.xcodeproj */, 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */, - 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */, 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */, 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */, 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */, @@ -938,6 +919,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, ); @@ -957,10 +939,6 @@ ProductGroup = ADBDB9201DFEBF0600ED6528 /* Products */; ProjectRef = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; }, - { - ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; - ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; - }, { ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */; ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; @@ -1036,13 +1014,6 @@ remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTGeolocation.a; - remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = { isa = PBXReferenceProxy; fileType = archive.ar;