Javascript 如何从量角器中的表中收集聚合数据并将其作为数组返回?

Javascript 如何从量角器中的表中收集聚合数据并将其作为数组返回?,javascript,angular,typescript,protractor,Javascript,Angular,Typescript,Protractor,我试图在量角器测试中,从数据表中聚合一个日期列表,以角度书写。我正在从量角器测试中调用的PageObject类进行聚合。我知道我的代码成功地捕获了我想要的文本,但是当我尝试对返回的数组进行console.log时,我得到了一个空数组。我还不熟悉Javascript/Typescript、Angular和Degrator,这可能是因为我对这个开发环境的异步特性还不熟悉 代码如下: 方法为的PageObject SpecMapper类: import { browser, element, by }

我试图在量角器测试中,从数据表中聚合一个日期列表,以角度书写。我正在从量角器测试中调用的PageObject类进行聚合。我知道我的代码成功地捕获了我想要的文本,但是当我尝试对返回的数组进行console.log时,我得到了一个空数组。我还不熟悉Javascript/Typescript、Angular和Degrator,这可能是因为我对这个开发环境的异步特性还不熟悉

代码如下:

方法为的PageObject SpecMapper类:

import { browser, element, by } from 'protractor';

export class SpecMapperPage {
    getImportDateSubmittedColumnValues() {
        let stringDatesArray: Array<string> = [];
        // currently this css selector gets rows in both import and export tables
        // TODO: get better identifiers on the import and export tables and columns
        element.all(by.css('md-card-content tbody tr.ng-tns-c3-0')).each(function(row, index){
            // check outerHTML for presence of "unclickable", the rows in the export table
            row.getAttribute('outerHTML').then(function(outerHTML:string) {
                // specifically look for rows without unclickable
                if(outerHTML.indexOf("unclickable") < 0){
                    // grab the columns and get the third column, where the date submitted field is
                    // TODO: get better identifiers on the import and export columns
                    row.all(by.css("td.ng-tns-c3-0")).get(2).getText().then(function(text:string) {
                       stringDatesArray.push(text);
                    });
                }
            });
        });
        return stringDatesArray;
    }
}
import { SpecMapperPage } from "./app.po";
import {browser, ExpectedConditions} from "protractor";

describe('spec mapper app', () => {
    let page: SpecMapperPage;
    let PROJECT_ID: string = '57';
    let PROJECT_NAME: string = 'DO NOT DELETE - AUTOMATED TESTING PROJECT';

    beforeEach(() => {
        page = new SpecMapperPage();
    });

    describe('import/export page', () => {
        it('verify sort order is desc', () => {
            browser.waitForAngularEnabled(false);
            // Step 1: Launch Map Data from Dashboard
            page.navigateTo(PROJECT_ID);
            browser.driver.sleep(5000).then(() => {
                // Verify: Mapping Screen displays
                // Verify on the specmapper page by checking the breadcrumbs
                expect(page.getProjectNameBreadCrumbText()).toContain(PROJECT_NAME);
                expect(page.getProjectMapperBreadCrumbText()).toEqual("MAPPER");

                // Verify: Verify Latest Submitted Date is displayed at the top
                // Verify: Verify the Submitted Date column is in descending order
                console.log(page.getImportDateSubmittedColumnValues());
            });
        });
    });
});
我承认此代码没有积极使用量角器的细节,我们的应用程序存在一个已知问题,在几个月内无法解决,因此我99%的时间直接访问驱动程序

您会注意到,我将上面发布的方法作为
browser.driver.sleep().then()
子句
page.getImportDateSubmittedColumnValues()
中的最后一行调用

我想我可能遇到了异步问题,调用是在页面加载之前完成的,因此我把它放在
.then()
子句中;但通过调试了解到情况并非如此。但是,一旦数组正确返回,这段代码应该可以工作

console.log正在打印一个空的
[]
数组。这与我在PageObject SpecMapper类中直接调试上述方法时看到的结果是同义的。我希望验证返回的字符串是否正确格式化,然后我将进行一些日期顺序比较。我觉得返回从页面检索到的数据数组并不是一个不寻常的请求,但我似乎找不到一个好方法来搜索我正在尝试做的事情

抱歉,如果我遇到了一些非常明显的障碍,我仍然在学习打字/角度/量角器的细微差别。谢谢您的考虑


我试图使用整理过的承诺似乎很有希望,但在执行时失败了

我更新的PageObject SpecMapper类

import {browser, element, by, protractor} from 'protractor';

export class SpecMapperPage {
    getImportDateSubmittedColumnValues() {
        let promisesArray = [];
        let stringDatesArray: Array<string> = [];
        // This CSS selector grabs the import table and any cells with the label .created-date
        element.all(by.css('.import-component .created-date')).each(function(cell, index) {
            // cell.getText().then(function(text:string) {
            //    console.log(text);
            // });
            promisesArray.push(cell.getText());
        });
        return protractor.promise.all(promisesArray).then(function(results) {
           for(let result of results) {
               stringDatesArray.push(result);
           }
           return stringDatesArray;
        });
    }
}
当我在PO类中的
返回stringDatesArray处设置断点时行,我在不同的作用域中有以下变量。请注意,promisesArray有3个对象,但进入
量角器.promise.all(
块)的结果数组有0个对象。我不确定我的断开连接是什么:/

我想我遇到了一个作用域问题,我在理解上遇到了问题。你会注意到
getText()
上注释掉的承诺解析,这是我的POC证明我得到了我期望的字符串值,所以我不确定为什么它在下面作为解决方案提供的承诺数组结构中不起作用



我能找到的唯一其他相关问题与获取表的特定行有关,而不是专门聚合要返回的数据,以便在量角器中进行测试验证。如果您感兴趣,可以找到它。

正如您提到的问题,是由console.log在变量执行之前返回变量值引起的已经有人居住了

我从这个答案中提取了一个片段,可以让您解决这个问题:

因此,在您的代码中

getImportDateSubmittedColumnValues() {
    let promisesArray = [];
    let stringDatesArray: Array<string> = [];
    // currently this css selector gets rows in both import and export tables
    // TODO: get better identifiers on the import and export tables and columns
    element.all(by.css('md-card-content tbody tr.ng-tns-c3-0')).each(function(row, index){
        // check outerHTML for presence of "unclickable", the rows in the export table
        row.getAttribute('outerHTML').then(function(outerHTML:string) {
            // specifically look for rows without unclickable
            if(outerHTML.indexOf("unclickable") < 0){
                // grab the columns and get the third column, where the date submitted field is
                // TODO: get better identifiers on the import and export columns
                promisesArray.push(row.all(by.css("td.ng-tns-c3-0")).get(2).getText());
            }
        });
    });
    return protractor.promise.all(promisesArray).then(function(results){
        // In here you'll have access to the results 

    });
}

正如您所提到的,问题是由console.log在实际填充变量之前返回变量值引起的

我从这个答案中提取了一个片段,可以让您解决这个问题:

因此,在您的代码中

getImportDateSubmittedColumnValues() {
    let promisesArray = [];
    let stringDatesArray: Array<string> = [];
    // currently this css selector gets rows in both import and export tables
    // TODO: get better identifiers on the import and export tables and columns
    element.all(by.css('md-card-content tbody tr.ng-tns-c3-0')).each(function(row, index){
        // check outerHTML for presence of "unclickable", the rows in the export table
        row.getAttribute('outerHTML').then(function(outerHTML:string) {
            // specifically look for rows without unclickable
            if(outerHTML.indexOf("unclickable") < 0){
                // grab the columns and get the third column, where the date submitted field is
                // TODO: get better identifiers on the import and export columns
                promisesArray.push(row.all(by.css("td.ng-tns-c3-0")).get(2).getText());
            }
        });
    });
    return protractor.promise.all(promisesArray).then(function(results){
        // In here you'll have access to the results 

    });
}
我不做打字脚本,但如果你只是想从你的方法中得到一系列的定位文本,类似的东西应该会起作用

getImportDateSubmittedColumnValues() {
    let stringDatesArray: Array<string> = [];

    $$('.import-component .created-date').each((cell, index) => {
        cell.getText().then(text => {
            stringDatesArray.push(text);
        });
    }).then(() => {
        return stringDatesArray;
    });
}
getImportDateSubmittedColumnValues(){
让stringDatesArray:Array=[];
$$('.import component.created date')。每个((单元格,索引)=>{
cell.getText().then(text=>{
stringDatesArray.push(文本);
});
}).然后(()=>{
返回字符串日期数组;
});
}
我不做打字脚本,但如果你只是想从你的方法中获取一系列定位文本,类似的东西应该可以用

getImportDateSubmittedColumnValues() {
    let stringDatesArray: Array<string> = [];

    $$('.import-component .created-date').each((cell, index) => {
        cell.getText().then(text => {
            stringDatesArray.push(text);
        });
    }).then(() => {
        return stringDatesArray;
    });
}
getImportDateSubmittedColumnValues(){
让stringDatesArray:Array=[];
$$('.import component.created date')。每个((单元格,索引)=>{
cell.getText().then(text=>{
stringDatesArray.push(文本);
});
}).然后(()=>{
返回字符串日期数组;
});
}

答案最终与发布在

最后一个PageObject类函数:

import {browser, element, by, protractor} from 'protractor';

export class SpecMapperPage {
    getImportDateSubmittedColumnValues() {
        let stringDatesArray: Array<string> = [];
        let promisesArray = [];
        // return a promise promising that stringDatesArray will have an array of dates
        return new Promise((resolve, reject) => {
            // This CSS selector grabs the import table and any cells with the label .created-date
            element.all(by.css('.import-component .created-date')).map((cell) => {
                // Gather all the getText's we want the text from
                promisesArray.push(cell.getText());
            }).then(() => {
                protractor.promise.all(promisesArray).then((results) => {
                    // Resolve the getText's values and shove into array we want to return
                    for(let result of results) {
                        stringDatesArray.push(result);
                    }
                }).then(() => {
                    // Set the filled array as the resolution to the returned promise
                    resolve(stringDatesArray);
                });
            });
        });
    }
}

最大的事情是等待不同的调用运行完成,然后等待stringDataArray被填充。这需要我在上面提到的SO帖子中找到的promise(resolve,reject)结构。我最终使用lambda
(()=>{})函数调用,而不是声明的
(function(){})
为了更清晰的外观,该方法在两种方式中都是一样的。其他建议的解决方案都没有成功地将字符串数组传播回我的测试。我正在使用带有量角器的Typescript进行工作。

答案最终与发布在

最后一个PageObject类函数:

import {browser, element, by, protractor} from 'protractor';

export class SpecMapperPage {
    getImportDateSubmittedColumnValues() {
        let stringDatesArray: Array<string> = [];
        let promisesArray = [];
        // return a promise promising that stringDatesArray will have an array of dates
        return new Promise((resolve, reject) => {
            // This CSS selector grabs the import table and any cells with the label .created-date
            element.all(by.css('.import-component .created-date')).map((cell) => {
                // Gather all the getText's we want the text from
                promisesArray.push(cell.getText());
            }).then(() => {
                protractor.promise.all(promisesArray).then((results) => {
                    // Resolve the getText's values and shove into array we want to return
                    for(let result of results) {
                        stringDatesArray.push(result);
                    }
                }).then(() => {
                    // Set the filled array as the resolution to the returned promise
                    resolve(stringDatesArray);
                });
            });
        });
    }
}

最大的事情是等待不同的调用运行完成,然后等待stringDataArray被填充。这需要我在上面提到的SO帖子中找到的promise(resolve,reject)结构。我最终使用lambda
(()=>{})函数调用,而不是声明的
(function(){})
为了更清晰的外观,该方法在两种方式中都是一样的。其他建议的解决方案都没有成功地将字符串数组传播回我的测试。我正在使用Typescript,带有量角器。

非常感谢您的参考,然后是将解决方案应用到我的代码的自定义示例。我已经更新了我的q
import { SpecMapperPage } from "./specMapper.po";
import {browser, ExpectedConditions} from "protractor";

describe('spec mapper app', () => {
    let page: SpecMapperPage;
    let PROJECT_ID: string = '57';
    let PROJECT_NAME: string = 'DO NOT DELETE - AUTOMATED TESTING PROJECT';

    beforeEach(() => {
        page = new SpecMapperPage();
    });

    describe('import/export page', () => {
        it('TC2963: ImportComponentGrid_ShouldDefaultSortBySubmittedDateInDescendingOrder_WhenPageIsLoaded', () => {
            browser.waitForAngularEnabled(false);
            // Step 1: Launch Map Data from Dashboard
            page.navigateTo(PROJECT_ID);
            browser.driver.sleep(5000).then(() => {
                // Verify: Mapping Screen displays
                // Verify on the specmapper page by checking the breadcrumbs
                expect(page.getProjectNameBreadCrumbText()).toContain(PROJECT_NAME);
                expect(page.getProjectMapperBreadCrumbText()).toEqual("MAPPER");

                // Verify: Verify Latest Submitted Date is displayed at the top
                // Verify: Verify the Submitted Date column is in descending order
                page.getImportDateSubmittedColumnValues().then((results) => {
                    console.log(results);
                });
            });
        });
    });
});