如何在 react-native detox 中按祖先索引匹配元素
How to match element by ancestor index in react-native detox
我正在尝试遵循 react-native 排毒的个人模式,其中包括如下内容:
export const noteCardDescriptor = (baseID: string) => (index: number) => {
return {
get element() {
return element(by.id(baseID)).atIndex(index);
},
get title() {
return element(
by.id('NoteCardTitle').withAncestor(by.id(baseID)),
).atIndex(index);
},
get date {
return element(by.id('NoteCardDate').withAncestor(by.id(baseID))).atIndex(
index,
);
},
};
};
class MyScreen {
static note = noteCardDescriptor('MyScreenNoteCard')
}
并在我的测试中像这样使用它:
const noteOne = MyScreen.note(0)
await expect(noteOne.title).toHaveText('Hello there')
await expect(noteOne.date).toNotBeVisible()
const noteTwo = MyScreen.note(1)
await expect(noteTwo.title).toHaveText('Hello there')
await expect(noteTwo.date).toHaveText(formatDate(date))
这种方法的问题是,当一个元素是可选的(如 date
)时,给定的索引将无法正确匹配,因为 detox 将匹配器读取为:
- 在
IDX
获取元素 Y
与祖先 X
而不是
- 在
IDX
找到祖先 X
并找到 ID 为 Y
的 child
所以我的问题是:
有什么方法可以让 detox 先搜索 IDX
的祖先,然后才找到 childrens 匹配吗?
像这样:
element(by.id(X).withAncestor(by.id(Y).atIndex(0))
注意:我知道我可以将可选字段 getter 转换为方法并覆盖索引,但阅读它会让人感到困惑,因为我之前已经指定了“'ancestor'”索引
Detox matchers 与您尝试使用它们的方式不太一样。如文档中所述:
Detox uses matchers to match UI elements in your app.
它们不适用于树遍历以提取元素。匹配器为您提供一组符合特定条件的元素。 atIndex 匹配器允许您指定在匹配器 returns 多个 UI 元素时选择哪个元素。
所以,你的例子
element(by.id(X).withAncestor(by.id(Y).atIndex(0))
应该理解为:找到所有UI个元素id为X
的元素,然后只保留其祖先id为Y
的元素,以及这些剩余的元素, 选择索引为 0 的那个。
文档强调了 atIndex 匹配器的一些问题,所以我建议不要使用它:
Due to different underlying implementations of Detox on iOS and Android, as well as other differences in the OS implementations, as well as RN implementation differences on each OS, indices may not match between iOS and Android. Relying on indices may also introduce flakiness in your tests as your app's user interface is updated. It is recommended to use unique identifier matchers for your elements.
我正在尝试遵循 react-native 排毒的个人模式,其中包括如下内容:
export const noteCardDescriptor = (baseID: string) => (index: number) => {
return {
get element() {
return element(by.id(baseID)).atIndex(index);
},
get title() {
return element(
by.id('NoteCardTitle').withAncestor(by.id(baseID)),
).atIndex(index);
},
get date {
return element(by.id('NoteCardDate').withAncestor(by.id(baseID))).atIndex(
index,
);
},
};
};
class MyScreen {
static note = noteCardDescriptor('MyScreenNoteCard')
}
并在我的测试中像这样使用它:
const noteOne = MyScreen.note(0)
await expect(noteOne.title).toHaveText('Hello there')
await expect(noteOne.date).toNotBeVisible()
const noteTwo = MyScreen.note(1)
await expect(noteTwo.title).toHaveText('Hello there')
await expect(noteTwo.date).toHaveText(formatDate(date))
这种方法的问题是,当一个元素是可选的(如 date
)时,给定的索引将无法正确匹配,因为 detox 将匹配器读取为:
- 在
IDX
获取元素Y
与祖先X
而不是
- 在
IDX
找到祖先X
并找到 ID 为Y
的 child
所以我的问题是:
有什么方法可以让 detox 先搜索 IDX
的祖先,然后才找到 childrens 匹配吗?
像这样:
element(by.id(X).withAncestor(by.id(Y).atIndex(0))
注意:我知道我可以将可选字段 getter 转换为方法并覆盖索引,但阅读它会让人感到困惑,因为我之前已经指定了“'ancestor'”索引
Detox matchers 与您尝试使用它们的方式不太一样。如文档中所述:
Detox uses matchers to match UI elements in your app.
它们不适用于树遍历以提取元素。匹配器为您提供一组符合特定条件的元素。 atIndex 匹配器允许您指定在匹配器 returns 多个 UI 元素时选择哪个元素。 所以,你的例子
element(by.id(X).withAncestor(by.id(Y).atIndex(0))
应该理解为:找到所有UI个元素id为X
的元素,然后只保留其祖先id为Y
的元素,以及这些剩余的元素, 选择索引为 0 的那个。
文档强调了 atIndex 匹配器的一些问题,所以我建议不要使用它:
Due to different underlying implementations of Detox on iOS and Android, as well as other differences in the OS implementations, as well as RN implementation differences on each OS, indices may not match between iOS and Android. Relying on indices may also introduce flakiness in your tests as your app's user interface is updated. It is recommended to use unique identifier matchers for your elements.