Angularjs 异步操作后尝试读取表行数据时遇到片状

Angularjs 异步操作后尝试读取表行数据时遇到片状,angularjs,xpath,protractor,angular-material,Angularjs,Xpath,Protractor,Angular Material,我有一个测试套件,它涉及从两个选择输入(使用角度材质)中进行选择,这反过来会在异步操作完成后触发一个表来呈现一些结果 操作完成后,我将尝试读取单个表行的值,以便对表单元格中的值执行一些断言 我正在使用两个帮助程序,其中一个使用字符串值并使用xpath查询来尝试提取一个表行,其中is查找一个包含表单元格的行,该表单元格包含传入的字符串 我面临的问题是我的期望expect(cells)。toBeDefined()返回未定义。这种情况是间歇性发生的,但我认为有75%的时间失败,因此我认为xpath

我有一个测试套件,它涉及从两个选择输入(使用角度材质)中进行选择,这反过来会在异步操作完成后触发一个表来呈现一些结果

操作完成后,我将尝试读取单个表行的值,以便对表单元格中的值执行一些断言

我正在使用两个帮助程序,其中一个使用字符串值并使用xpath查询来尝试提取一个表行,其中is查找一个包含表单元格的行,该表单元格包含传入的字符串

我面临的问题是我的期望
expect(cells)。toBeDefined()
返回未定义。这种情况是间歇性发生的,但我认为有75%的时间失败,因此我认为xpath方法可能不合适,或者我至少应该在尝试任何断言之前尝试并等待至少一行数据出现。这在我们的ci服务器(Jenkins)上是最糟糕的,因为它很少通过,所以我觉得这是一个时间问题

量角器对测试失败的截图如下:

这里选择了比较期输入,并且表中确实显示了一条记录,因此我觉得这是一个计时问题,在异步获取数据完成和执行预期之间,数据行在表中没有完全呈现

有人对我可以在这里尝试的东西有什么建议吗?有什么我应该遵循的推荐食谱吗?

我建议。这似乎更适合你的情况

只需通过元素链接,就可以一次性获得所需的行

它将是这样的:

cells = element(by.cssContainingText('td span', 'TAYSIDE')).element(by.xpath('ancestor::tr')).all(by.css('td'));
//first part selects the element of the desired row
//second part of the chain selects the next <tr>-parent-element above
//third part selects all td-elements below the selected <tr>-element

//alternatives:
cells = element(by.cssContainingText('td span', value)).element(by.xpath('..')).$$('td');
//by.xpath('..') to select direct parent
//"$$()" is short for "element.all(by.css())"
describe("full scenario", function(){
    var cells;

    beforeAll(function(){
        common.selectComparisonPeriod(initialPeriod);
        //probably no need to use "then()" here.
        browser.wait(helper.waitForElementToHide(common.spinner), 5000);
        cells = element(by.cssContainingText('td span', value))
            .element(by.xpath('ancestor::tr'))
            .$$('td');
    });
    it("executes test", function(){
        expect(cells).toBeDefined();
    });
});
更多选项:

  • 使用
    it()
    而不是
    beforeAll()
  • 使用
    browser.wait()
    -条件确保单元格定义
代码:

describe("full scenario", function(){
    var cells;

    //instead beforeAll, use another it()-block
    it("shall load the correct grid", function(done){
        common.selectComparisonPeriod(initialPeriod);
        //probably no need to use "then()" here.
        browser.wait(helper.waitForElementToHide(common.spinner), 5000);
        cells = element(by.cssContainingText('td span', value))
            .element(by.xpath('ancestor::tr'))
            .$$('td');
        done();
    });
    it("executes test", function(){
        //simplest to just wait for all promises to be resolved (if controlFlow enabled)
        browser.waitForAngular(); 
        //waits until cells is defined, but for max 5 secs
        browser.wait(typeof(cells) != 'undefined', 5000); 
        expect(cells).toBeDefined();
    });
});

谢谢你的建议,但是我从量角器中得到了相同的未定义错误。你在
beforeAll()之前定义了单元格吗?因为我只是这么想。我还假设您的助手函数使用了
browser.wait()
。现在我给出了一个完整的示例,其中我将helper函数另外包装在一个
browser.wait()
中,以防函数返回true/false。我还删除了
then()
。。。这里不需要。谢谢,我的
waitForElementToHide
帮助程序确实使用了browser.wait,并且是
单元格
已经在
之前
之外定义。将根据您的选择尝试一些变体…@mindparse:谢谢您的回复。我想补充一件事(你可能已经知道了,但无论如何)是我删除了
.then()
,因为它打开了一个异步任务,而没有
then()
量角器应该保持执行同步。还有一件事,可以使用
browser.waitForAngular()cells=…
之前的行中的code>,以确保在单元格定义之前没有未解决的承诺。还有
console.log(cells.toString())可以是一个指示器;它是返回
[object object]
还是
未定义的
@mindparse:我想到了一个问题:为什么你要费心在
之前将逻辑放入
中,而只在
中签入它
?由于每个
之前都没有
,所以在
it
-语句中包含所有内容对我来说似乎更符合逻辑。