From 51ac0def092df48693dcf8cf5e8fee307f027745 Mon Sep 17 00:00:00 2001 From: Mina Nagy Zaki Date: Thu, 12 Sep 2019 18:41:35 +0200 Subject: [PATCH] chore(e2e/utils): improve readVisibleText - find Text element by type - try to also find a Text child of the given testID - handle matching multiple children and read each recursively --- e2e/utils.ts | 83 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 76 insertions(+), 7 deletions(-) diff --git a/e2e/utils.ts b/e2e/utils.ts index 4f6181dfa4..faceba3439 100644 --- a/e2e/utils.ts +++ b/e2e/utils.ts @@ -1,13 +1,75 @@ import { expect } from 'detox' +// https://github.com/wix/Detox/blob/master/docs/APIRef.Matchers.md#bytypenativeviewtype +const nativeTypesNames = ['Text', 'Image'] +const buildTypeMap = (typeNameBuilder: (typeName: string) => string): {[k: string]: string} => { + let ret = {} + nativeTypesNames.forEach(typeName => ret[typeName] = typeNameBuilder(typeName)) + return ret +} +export const nativeTypes = device.getPlatform() == 'android' ? + buildTypeMap(typeName => `android.widget.${typeName}View`) : + buildTypeMap(typeName => `RCT${typeName}View`) + /** * @async - * @desc Given a testID of a element, returns the visible text in it - * courtsey of https://github.com/wix/detox/issues/445#issuecomment-514801808 + * @desc Returns the visible text from the element with testID + * initially based on https://github.com/wix/detox/issues/445#issuecomment-514801808 + * @param testID the testID of a element or a parent of one or more + * elements. If more than one is found the result is + * concatted + * @param index index of element value to return, instead of all + * concatted children. Leave undefined for default behavior + * @returns visibleText all text visible inside the element with testID */ -export const readVisibleText = async (testID: string) => { +export const readVisibleText = async (testID: string, index: number | undefined = undefined): Promise => { + let el = element(by.id(testID).and(by.type(nativeTypes.Text))) + if (index !== undefined) { + //console.error('with index', index) + el = el.atIndex(index) + } + try { + await expect(el).toBeVisible() + } catch (err) { + // try looking for a text child + el = element(by.type(nativeTypes.Text).withAncestor(by.id(testID))) + if (index !== undefined) { + //console.error('with index with text child', index) + el = el.atIndex(index) + } + + try { + //console.error('expect with child') + await expect(el).toBeVisible() + } catch (err) { + const msg = err.message.toString() + if (msg.indexOf('matches multiple views in the hierarchy') == -1) { + // if it is any other error than matching multiple views, we raise it + //console.error('expect with child error', err) + throw err + } + + // if there are multiple matching Text views, we try to get the + // concatenated text + const MAX_TEXT_CHILDREN = 100 + const texts = [] + for (let i = 0; i < MAX_TEXT_CHILDREN; i++) { + try { + const text = await readVisibleText(testID, i) + texts.push(text) + } catch (err) { + // TODO how do we know there are no more children vs. some other + // error? + break + } + } + + return texts.join('') + } + } + try { - await expect(element(by.id(testID))).toHaveText('_you_cant_possible_have_this_text_') + await expect(el).toHaveText('_you_cant_possible_have_this_text_') throw 'are you kidding me?' } catch (error) { if (device.getPlatform() === 'ios') { @@ -24,9 +86,16 @@ export const readVisibleText = async (testID: string) => { const [, restMessage] = errorMessage.split(start); const [label] = restMessage.split(end); const value = label.split(','); - var combineText = value.find((i: string) => i.includes('text=')).trim(); - const [, elementText] = combineText.split('='); - return elementText; + let combineText = value.find((i: string) => i.includes('text=')) + if (!combineText) { + throw new Error( + `readVisibleText failed! '${testID}' must be a testID of a element (or a parent of one)` + ) + } else { + combineText = combineText.trim() + } + const [, elementText] = combineText.split('=') + return elementText } } }