1

Okay, this one has me scratching my head. I've got getDataArrayForTargetColumn defined:

async getDataArrayForTargetColumn() {
    if (await page.waitForSelector('[data-test-value-invoice-number-payment-requests-page="true"]')) {
        let targetColumnDataArray = await page.evaluate(() => {
            let tds = Array.from(document.querySelectorAll('[data-test-value-invoice-number-payment-requests-page="true"]'));
            return tds.map(td => td.textContent.trim());
        });
        return targetColumnDataArray;
    }
    return settings._neg_1;
}

and getDataArrayForTargetColumn2 defined:

async getDataArrayForTargetColumn2(someCssSelector) {
    if (await page.waitForSelector(someCssSelector)) {
        let targetColumnDataArray = await page.evaluate(() => {
            let tds = Array.from(document.querySelectorAll(someCssSelector));
            return tds.map(td => td.textContent.trim());
        });
        return targetColumnDataArray;
    }
    return settings._neg_1;
}

And when called:

async verifySomething{
    let columnData = await this.getDataArrayForTargetColumn();
    let someCssSelector = '[data-test-value-invoice-number-payment-requests-page="true"]';
    let columnData2 = await this.getDataArrayForTargetColumn2(dog);
}

The first one, columnData, works and the second one, columnData2, does not. columnData2 gives me a:

Error: Evaluation failed: ReferenceError: someCssSelector is not defined

but it clearly is. When I put breakpoints, it seems to die at the let targetColumnDataArray = await page.evaluate(() => {

So, what's going on folks? Why can't I pass a variable in? Am I missing something stupid here?

============================================================

UPDATE:

This still doesn't work if I move the defining the CSS Selector to within the local function.

async getDataArrayForTargetColumn2() {
    let someCssSelector = '[data-test-value-invoice-number-payment-requests-page="true"]';
    if (await page.waitForSelector(someCssSelector)) {
        let targetColumnDataArray = await page.evaluate(() => {
            let tds = Array.from(document.querySelectorAll(someCssSelector));
            return tds.map(td => td.textContent.trim());
        });
        return targetColumnDataArray;
    }
    return settings._neg_1;
}
Huckleberry Carignan
  • 2,002
  • 4
  • 17
  • 33
  • The evaluated function is serialized and deserialized. It does not have the standard lexical scoping that you'd expect in all other normal areas of JS. – CertainPerformance Feb 24 '21 at 16:43
  • I'm still confused. Even when I define the CSS Selector local to the function, it is not being passed into the querySelectAll, but it is being evaluated by the page.waitForSelector. Why is this happening? – Huckleberry Carignan Feb 24 '21 at 18:31
  • Read the duplicate and its answers more closely. You'll note that the answers recommend passing the variable as a parameter to the arrow function passed to `evaluate`. In your case, `page.evaluate((someCssSelector) => { ... }, someCssSelector)`. – Heretic Monkey Feb 24 '21 at 18:40
  • The function containing the `waitForSelector` call does not get serialized, so `someCssSelector` is available normally, as you'd expect. But the *callback* passed to `page.evaluate` gets serialized into a string and does not have the normal intuitive outer lexical scope availability you'd expect in nearly any other area of JS. – CertainPerformance Feb 24 '21 at 18:46

0 Answers0