CodeceptJS - unable to run any window. or document. line

Hi,
I have tried thousands of different things and I’m always receiving below error message.

message: “document is not defined”
stack: "ReferenceError: document is not defined↵

  var objarray = I.executeScript(function(_locator) { return document.querySelectorAll(_locator)});
  var i = 0;
  for (i ; i < objarray.length; i++) {
  	I.seeAttributesOnElements(objarray.item[i],{ 'aria-expanded': "false"});
  	objarray.item[i].click();
  	I.seeAttributesOnElements(objarray.item[i],{ 'aria-expanded': "true"});
  }

I tried with NO success with these two plugins also:

What does everyone do to use document.XXXXXX?

Thank you,

Please, paste more info in your question:
where do you run this code? is it helper or test ? which helper, driver and browser do you use?

where does it fails? runtime? or Typescript compile-time?

do you use session or run code in iframe?

I seen something similar to your code.
It was TS-linter or TS error, cause TS was not know that context is the browser. It solved by //@ts-ignore

Hi, thank you for guiding me with your questions

Visual Studio Code
image

SCENARIO is under F-ActivitiesActivityDetails_test.js, and it unique line is calling ExpandCollapse method from ButtonLink.

///
///

Feature(‘Feature:’);

//Scenarios

//Activity Options|Collapse buttons

BeforeSuite((I) => {
});

Before((I) => {

I.amOnPage(‘any web’);

I.waitForNavigation;

});

Scenario(‘Scenario: Activity Options|Collapse buttons’, (I,ButtonLink) => {

ButtonLink.ExpandCollapse(’.ams-activities-details-panel__icon’);

});

After((I) => {

pause();

});

AfterSuite((I) => {

});

ButtonLink.js complete file data:

///

const I = actor();

module.exports = {
// insert your locators and methods here
//Methods
ButtonLinkValidation(_locator,_currenturlvalidation){
I.click(_locator);
I.waitForNavigation;
I.seeInCurrentUrl(_currenturlvalidation);
},
ButtonLinkValidationNewTab(_locator,_currenturlvalidation){
I.click(_locator);
I.wait(5);
I.switchTo();
I.waitForNavigation;
I.seeInCurrentUrl(_currenturlvalidation);
I.closeCurrentTab();
},
ExpandCollapse(_locator){
var objarray = I.executeScript(function(_locator) { return document.querySelectorAll(_locator)});
var i = 0;
for (i ; i < objarray.length; i++) {
I.seeAttributesOnElements(objarray.item[i],{ ‘aria-expanded’: “false”});
objarray.item[i].click();
I.seeAttributesOnElements(objarray.item[i],{ ‘aria-expanded’: “true”});
}
}
}

codecept.json

{
“tests”: “./*_test.js”,
“timeout”: 10000,
“output”: “./output”,
“helpers”: {
“Puppeteer”: {
“url”: “http://localhost”,
“waitForNavigation”: [ “domcontentloaded”, “networkidle0” ],
“show”: true,
“windowSize”: “1366x768”,
“WebDriver” : {
“url”: “http://localhost”,
“browser”: “chrome”
}
}
},
“include”: {
“I”: “./steps_file.js”,
“SignInOut”: “./PageObject/SignInOut.js”,
“ButtonLink”: “./PageObject/ButtonLink.js”
},

“plugins”: {
“allure”: {},
“stepByStepReport”: {
“enabled”: true,
“screenshotsForAllureReport”: true
}
},

“gherkin”: {
“features”: “./features/*.feature”,
“steps”: [
“./step_definitions/steps.js”
]
},
“multiple”: {
“basic”: {
“browsers”: [“chrome”, “firefox”]
}
},
“bootstrap”: false,
“mocha”: {},
“name”: “wyn_auto”
}

I’m using puppeteer and currently using this command line:

npx --node-arg=–inspect-brk codeceptjs run F-ActivitiesActivityDetails_test.js --debug

How can I provide this?

where does it fails? runtime? or Typescript compile-time?
do you use session or run code in iframe?

Thank you

Not worked with Puppeteer.
But I see 2 possible problems

  1. There are no access to “http://localhost/any%20web
  2. You use one of the last versions of codecept, where page objects and helpers inject method was changed form const I = actor(); to const { I } = inject();
    see https://codecept.io/pageobjects#pageobject

Also, you do not send argument _locator to function in execute script.
You should add it as argument to executeScript after function:
I.executeScript(function(_locator) { return document.querySelectorAll(_locator)}, _locator);
see 2nd example from section https://codecept.io/helpers/Puppeteer/#executescript

1 Like

Thank you, I have tried all suggestions and still document is not defined

Hi @nifepo,

Have you found any solution? I’m facing the same problem…

Hello all,

I have had a similar issue in the past. The way I solved it was to implement a helper using executeScript function rather than using it in a pageObject. This is for WebDriver however, so you will need to probably adapt the implementation to puppeteer:

This is inside my wdio-helper file

    /**
     * This functions is focused on helping to click elements by index
     * @param {String} selector - string selector - CSS mandatory
     * @param {Number} index - position of the locator if in array of elements
     */
    async clickByIndex(selector, index = 0) {
        const helper = this.helpers.WebDriver;

        return helper.executeScript(async (selector, index) => {
            document.querySelectorAll(selector)[index].click();
        }, selector, index);
    }

    /**
     * This functions is focused on helping to click elements by index
     * @param {String} selector - string selector - CSS mandatory
     * @param {Number} index - position of the locator if in array of elements
     * @param {String} attribute - the element attribute of interest
     */
    getElementAttrByIndex(selector, index = 0, attribute) {
        const helper = this.helpers.WebDriver;
        // const helper = this.helpers.Puppeteer; // this is the helper you want to use instead of WebDriver

        return helper.executeScript(async (selector, index, attribute) => {
            await document.querySelectorAll(selector)[index].getAttribute(attribute);
        }, selector, index, attribute);
    }

after this in your tests you should be able to just do this

await I.clickByIndex('#someSelector', 1); // 1 stands for the index as per implementation
await I.getElementAttrByIndex('#someSelector', 0, 'href'); // this returns the href attribute of the element

Made sure this works still and checked the code now, everything running correctly and as expected.

2 Likes

For debugging, depending on the IDE you use, you can have different setups.

VSCode Debug Config:

{
  "type": "node",
  "request": "launch",
  "name": "codeceptjs",
  "args": ["run", "--grep", "@your_test_tag"],
  "program": "${workspaceFolder}/node_modules/.bin/codeceptjs"
}

VSCode Debug

If you add the command to your scripts section in package.json so you can run it with something like npm run test

in package.json

"scripts": {
    "test": "./node_modules/.bin/codeceptjs run"

you can easily change your debug config to this in JetBrains based IDEs (WebStorm, IntelliJ, etc)

1 Like

I can’t find the wdio-helper file anywhere. I installed the wdio CLI and also the helpers using npm, but still cant find the helper file. Can you point to the directory?

That’s because it is a custom helper file I created. Here’s the full file:

const Helper = codecept_helper;

const pageLoaded = browser =>
    browser.waitUntil(async () => {
        const state = await browser.execute('return document.readyState');
        return state === 'complete';
    }, 15000, 'Page load timed out!', 2000);

class WdioHelper extends Helper {
    async locateElement(selector) {
        const codecept = this.helpers.WebDriver;
        return codecept._locate(selector, true).then(res => !!res)
            .catch((e) => { throw new Error(`Error occured on the selector: ${e.message}`); });
    }

    checkIfVisible(selector) {
        const wdio = this.helpers.WebDriver.browser;

        return wdio.waitUntil(async () => await this.locateElement(selector) === true, 10000).then(res => !!res)
            .catch((e) => { throw new Error(`Error occured on the selector: ${e.message}`); });
    }

    async lookForVisibleElement(selector, seconds = 5) {
        const codecept = this.helpers.WebDriver;
        return codecept._locate(selector, true).then((res) => {
            if (res && res.length > 0) {
                return true;
            }
            return false;
        }).catch((e) => { throw new Error(`Error occured on the selector: ${e.message}`); });
    }

    async waitVisible(selector) {
        const helper = this.helpers.WebDriver;
        try {
            helper.waitForVisible(selector);
            const numVisible = await helper.grabNumberOfVisibleElements(selector);

            return parseInt(numVisible, 10) > 0;
        } catch (err) {
            throw new Error(`Element not found - stack: ${err}`);
        }
    }

    async clickIfVisible(selector) {
        const helper = this.helpers.WebDriver;
        try {
            const numVisible = await helper.grabNumberOfVisibleElements(selector);

            if (numVisible) {
                return helper.click(selector);
            }
        } catch (err) {
            throw new Error(`Element not found - stack: ${err}`);
        }
    }
    /**
     * This functions is focused on helping to click elements by index
     * @param {String} selector - string selector - CSS mandatory
     * @param {Number} index - position of the locator if in array of elements
     */
    async clickByIndex(selector, index = 0) {
        const helper = this.helpers.WebDriver;

        return helper.executeScript(async (selector, index) => {
            document.querySelectorAll(selector)[index].click();
        }, selector, index);
    }

    /**
     * This functions is focused on helping to click elements by index
     * @param {String} selector - string selector - CSS mandatory
     * @param {Number} index - position of the locator if in array of elements
     * @param {String} attribute - the element attribute of interest
     */
    getElementAttrByIndex(selector, index = 0, attribute) {
        const helper = this.helpers.WebDriver;

        return helper.executeScript(async (selector, index, attribute) => {
            await document.querySelectorAll(selector)[index].getAttribute(attribute);
        }, selector, index, attribute);
    }

    async waitForPageLoad() {
        const { browser } = this.helpers.WebDriver;
        return pageLoaded(browser);
    }

    async goToPage(url) {
        const { browser } = this.helpers.WebDriver;

        browser.url(url);
        return pageLoaded(browser);
    }
}

module.exports = WdioHelper;