我正在尝试使用Spectron来测试我的Electron应用程序。文档说,在尝试查找第n个子节点时,您可以使用第n个子选择器,或者使用$$
获取与选择器匹配的所有子节点,然后使用索引运算符,即$$ ("foo")[0]
获取第一个foo。 DOCS
有了这些知识,我希望输出以下代码:BAR
我无法解决这个问题,我尝试以下方法:
const foo = ".foo";
const fooElements = app.client.$$ (foo);
console.log ("FOOELEMENTS", await TP (app.client.getHTML (foo)));
console.log ("BAR", fooElements[0].getText (".bar"));
获得以下输出:
console.log components\pages\analysis\__test__\Analysis.spectron.ts:44
FOOELEMENTS [ '<div class="foo"><div class="bar">BAR</div><div class="baz">BAZ</div></div>',
'<div class="foo"><div class="bar">BAR2</div><div class="baz">BAZ2</div></div>',
'<div class="foo"><div class="bar">BAR3</div><div class="baz">BAZ3</div></div>'
'<div class="foo"><div class="bar">BAR4</div><div class="baz">BAZ4</div></div>' ]
console.log components\pages\analysis\__test__\Analysis.spectron.ts:50
EXCEPTION TypeError: Cannot read property 'getText' of undefined
at components\pages\analysis\__test__\Analysis.spectron.ts:45:44
at Generator.next (<anonymous>)
at fulfilled (components\pages\analysis\__test__\Analysis.spectron.ts:4:58)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
正如您所看到的,输出HTML确实有几个.foo
div,但当我尝试访问第一个时,它表示fooElements[0]
为undefined
sideNote(不应该相关):TP
是我写的一个名为toPromise
的函数的别名,它让我等待webdriver的承诺,因为TypeScript被实现的方式搞糊涂了:
export async function toPromise<T> (client: Webdriver.Client<T>)
{
return client as any as Promise<T>;
}
// Promise
interface Client<T> {
finally(callback: (...args: any[]) => void): Client<T>;
then<P>(
onFulfilled?: (value: T) => P | Client<P>,
onRejected?: (error: any) => P | Client<P>
): Client<P>;
catch<P>(
onRejected?: (error: any) => P | Client<P>
): Client<P>;
inspect(): {
state: "fulfilled" | "rejected" | "pending";
value?: T;
reason?: any;
};
}
知道我做错了什么吗?或建议的替代方案?如果可能的话,我更愿意避免使用nth-child选择器。
编辑:改为上课
答案 0 :(得分:1)
实际上,webdriver窗口索引和元素将[1]称为第一个元素。
这对我来说很好。
var button = ('//*[contains(@class,"popper")]')[1];
返回this.app.client.click(button);
示例:
class Clix {
constructor() {
this.clix_search = '(//input[contains(@class,"clix-search")])[1]';
}
clix_input_search(app) {
return help.setValue(app, this.clix_search, "pack");
}
}
在帮助程序类中
setValue(app, element, text) {
return app.client.waitForVisible(element, 60000)
.waitForEnabled(element, 60000)
.clearElement(element)
.setValue(element, text)
.getValue(element)
.should.eventually.equal(text)
}
答案 1 :(得分:0)
首先,你的例子很有趣。我不知道你是如何得到那条<html>
的。 id
值必须是唯一的:
id属性指定HTML元素的唯一ID(值 在HTML文档中必须是唯一的。)
您的代码应在稍作更改后才能生效,只需删除#bar
选择器即可。您正在将选择器传递给ELEMENT
对象,但它已通过selector
键的值包含该信息。
let locator = 'span[connectqa-device="installed"]'
browser.debug()
输出( debug-mode 中的阻止测试):
> let elems = $$(locator)
[18:10:22] COMMAND POST "/wd/hub/session/775b024e-0b6a-4a60-a5b2-26d4df961d0a/elements"
[18:10:22] DATA {"using":"css selector","value":"span[connectqa-device=\"installed\"]"}
[18:10:22] RESULT [{"element-6066-11e4-a52e-4f735466cecf":"c6719646-30da-43ff-9b17-40c074b4988a"},{"element-6066-11e4-a52e-4f735466cecf":"d5f8acf2-8f4f-4554-9fe6-7f863555f5b5"},{"element-6066-11e4-a52e-4f735466cecf":"53ff9b0a-2a88-4b13-9e54-9c54411c03c5"}]
> elems[0]
{ ELEMENT: 'c6719646-30da-43ff-9b17-40c074b4988a',
'element-6066-11e4-a52e-4f735466cecf': 'c6719646-30da-43ff-9b17-40c074b4988a',
selector: 'span[connectqa-device="installed"]',
value: { ELEMENT: 'c6719646-30da-43ff-9b17-40c074b4988a' },
index: 0 }
>
> elems[0].selector
'span[connectqa-device="installed"]'
>
> elems[0].getText()
[18:10:54] COMMAND GET "/wd/hub/session/775b024e-0b6a-4a60-a5b2-26d4df961d0a/element/c6719646-30da-43ff-9b17-40c074b4988a/text"
[18:10:54] DATA {}
[18:10:54] RESULT "Installed"
'Installed'
或者,您可以这样做:let retText2 = browser.getText('span[connectqa-device="installed"]')
> let retText2 = browser.getText(elems[0].selector)
。第二个例子当然只是出于教学目的,因为你可能永远不会想那样。
希望它有所帮助。干杯!