0

I am new to typescript and looking to scrape a list of values from an ag-grid column and compare it against a string array. Here is the function I wrote to achieve that. But my ActualRatingsValues.push(text); does not seem to be populating the array ActualRatingsValues. I don't really understand how promises work. Is this to do with promises ?

validateRatingsValues() {
   const ExpectedRatingsValues: Array<string> = ['A', 'B', 'C', 'D', 'E'];
   const ActualRatingsValues: Array<string> = [];
   const wrapper = element.all(by.css('.ag-pinned-left-cols-container div[col-id="name"]'))
            .getText()
            .then(text => {
                ActualRatingsValues.push(text);
            });

    let match = true;
    if (ExpectedRatingsValues != null && ActualRatingsValues != null) {
        if (ExpectedRatingsValues.length !== ActualRatingsValues.length) {
            match = false;

        } else {
            for (let i = 0; i < ActualRatingsValues.length; i++) {
                if (ActualRatingsValues[i].toString !== 
                    ExpectedRatingsValues[i].toString) {
                    match = false;
                    break;
                }
            }
        }
    } else {
        match = false;
    }

    expect(match).toBeTruthy();
}
yong
  • 13,357
  • 1
  • 16
  • 27
njosep
  • 380
  • 3
  • 14
  • FYI it's good practice that your test are between 10-12 lines of code – Patricio Vargas Aug 23 '18 at 15:27
  • most of it is the compare code that I can move out to another function. but I am stuck trying to get the values from the page into an array. Any advise ? – njosep Aug 23 '18 at 15:45
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Matt McCutchen Aug 23 '18 at 16:21

2 Answers2

1

There are two issues in your code.

1) ActualRatingsValues.push(text) should be ActualRatingsValues.concat(text)

because element.all().getText() return a promise which eventual value is an string array, not a string.

2) wrapper is a promise, you assign value to ActualRatingsValues within a promise. In order to consume ActualRatingsValues, you have to consume it inside promise then()

validateRatingsValues() {
    const ExpectedRatingsValues: Array<string> = ['A', 'B', 'C', 'D', 'E'];
    const wrapper = element.all(by.css('.ag-pinned-left-cols-container div[col-id="name"]'))
            .getText();

    let match = wrapper.then(function(ActualRatingsValues) {
        let length = ExpectedRatingsValues.length;

        for(let i=0;i<length;i++) {
            let find = ActualRatingsValues.includes(ExpectedRatingsValues[i]);
            if (find === false) {
                return find;
            }           
        }

        return true;     
    });

    // match is also a promise which eventual value is a boolean
    // why below expect doesn't consume match inside then()
    // because Jasmine can detect match is a promise and do the assertion
    // inside then() in its implement internally.
    expect(match).toBeTruthy();
}
yong
  • 13,357
  • 1
  • 16
  • 27
0

I'm actually surprised you aren't getting an error trying to push to ActualRatingsValues since it is a const.

What's happening here is the lines following your getText() call are actually being executed before all the promises are returned. That's why it seems like it isn't working. The easiest option would be to implement async/await.

Here is what that would look like: (note that I also cleaned up the code a bit)

async validateRatingsValues() {
    const ExpectedRatingsValues: Array<string> = ['A', 'B', 'C', 'D', 'E'];

    // this will wait for all the promises to be returned before proceeding
    const wrapper = await element.all(by.css('.ag-pinned-left-cols-container div[col-id="name"]'))
              .getText()

    wrapper.forEach(item => {
        expect(ExpectedRatingsValues.indexOf(item)).toBeGreaterThan(-1);

        // this should work too
        expect(ExpectedRatingsValues).toContain(item);
    }

    expect(wrapper.length).toEqual(ExpectedRatingsValues.length);
}

There are definitely ways to get this working without implementing async/await. I tried briefly to create an example and then realized my example wasn't going to work. I suggest reading the question/answer that Matt posted in the comments for a better understanding. There is a lot of good info in there.

tehbeardedone
  • 2,833
  • 1
  • 15
  • 23