CodeceptJS
CodeceptJS copied to clipboard
fillField will not auto-await elements when using TestCafe
What are you trying to achieve?
I want to fill in the fields on the login page of a SPA that takes a bit to load in and render the login page.
What do you get instead?
Unless you use I.waitForElement
to explicitly wait for the login form to load CodeceptJS will not fill out the fields, despite the fact that TestCafe has an auto-await system to wait for the field to be available before it fills in the field. This is because Codecept's TestCafe.js' findElements
sets timeout: 0
on the Selector which disables the auto-await.
Provide console output if related. Use
--verbose
mode for more details.
-- FAILURES:
1) Login
should login client:
TestCafe Error: {"filename":"...\\node_modules\\codeceptjs\\lib\\helper\\TestCafe.js","lineNum":384,"callsiteFrameIdx":5,"stackFrames":[{},{},{},{},{},{}],"isV8Frames":true} Selector('Username'),.with({ timeout: 0, boundTestRun: <ref *1> TestController { _executionContext: null, testRun: TestRun { captureRejections: false, _clientEnvironmentPrepared: false, _messageBus: [MessageBus], warningLog: [WarningLog], opts: [Object], test: [Test], browserConnection: [BrowserConnection], unstable: false, browser: [Object], phase: 'inTest', driverTaskQueue: [], testDoneCommandQueued: false, activeDialogHandler: null, activeIframeSelector: null, speed: 1, pageLoadTimeout: 30000, testExecutionTimeout: null, disablePageReloads: false, disablePageCaching: false, disableMultipleWindows: false, requestTimeout: [Object], session: [SessionController], consoleMessages: [BrowserConsoleMessages], pendingRequest: [Object], pendingPageError: null, controller: [Circular *1], ctx: [Object: null prototype] {}, fixtureCtx: [Object: null prototype] {}, testRunCtx: [Object: null prototype] {}, currentRoleId: null, usedRoleStates: [Object: null prototype] {}, errs: [], lastDriverStatusId: '6177.9000000059605', lastDriverStatusResponse: null, fileDownloadingHandled: false, resolveWaitForFileDownloadingPromise: null, attachmentDownloadingHandled: false, addingDriverTasksCount: 0, debugging: false, debugOnFail: false, disableDebugBreakpoints: false, debugReporterPluginHost: [ReporterPluginHost], browserManipulationQueue: [BrowserManipulationQueue], debugLog: [TestRunDebugLog], quarantine: null, debugLogger: [Object], observedCallsites: [ObservedCallsitesStorage], compilerService: undefined, asyncJsExpressionCallsites: Map(0) {}, replicator: [Object], disconnected: false, errScreenshotPath: null, startRunExecutionTime: 2022-06-21T23:26:15.230Z, runExecutionTimeout: null, preventEmitActionEvents: false, [Symbol(testRun)]: true
}, executionChain: Promise { _then: undefined, then: [Function (anonymous)], _testController: [Circular *1], _handled: true, _state: 'fulfilled', _data:
undefined }, warningLog: WarningLog { messageInfos: [], globalLog: [WarningLog], callback: [AsyncFunction (anonymous)], _isCopying: false } } }),.nth(0)
at mapError (node_modules\codeceptjs\lib\helper\testcafe\testcafe-utils.js:32:9)
at invokeCallback (node_modules\pinkie\index.js:60:12)
at Array.forEach (<anonymous>:null:null)
at publish (node_modules\pinkie\index.js:147:32)
at Array.publishRejection (node_modules\pinkie\index.js:157:2)
at Immediate.asyncFlush (node_modules\pinkie\index.js:17:19)
at processImmediate (node:internal/timers:468:21)
at process.topLevelDomainCallback (node:domain:152:15)
at process.callbackTrampoline (node:internal/async_hooks:128:24)
Scenario Steps:
- I.fillField("Username", "Example") at Test.<anonymous> (.\tests\e2e\codecept\features\Login.ts:41:7)
- I.waitForElement("h1") at Test.<anonymous> (.\tests\e2e\codecept\features\Login.ts:37:7)
- I.amOnPage("https://ugz04n.csb.app/") at Test.<anonymous> (.\tests\e2e\codecept\features\Login.ts:34:7)
Artifacts:
Provide test source code if related
Feature('Login');
Scenario('should login client', async ({ I }) => {
I.amOnPage('https://ugz04n.csb.app/');
// Wait for the h1 to appear, this makes the demo consistent (skips any delay Codesandbox adds) so we start
// the test at the same point where there is a consistent 1s delay between this point and when the form displays
I.waitForElement('h1');
// The test fails unless you uncomment the following to explicitly wait for the element to show up
// I.waitForElement('#username');
// Actual test, fails normally because these don't wait for the element, due to Codecept setting `timeout: 0`
I.fillField({ css: '#username' }, 'Example');
I.fillField({ css: '#password' }, secret('invalid'));
I.click('Log in');
});
Details
- CodeceptJS version: 3.3.3
- NodeJS Version: v16.15.1
- Operating System: Windows 10
- puppeteer || webdriverio || testcafe version (if related) [email protected]
- Configuration file:
require('ts-node/register');
const { setHeadlessWhen, setTestHost } = require('@codeceptjs/configure');
if (process.env.profile === 'undefined') {
delete process.env.profile;
}
setHeadlessWhen(process.env.CI);
setTestHost(process.env.TEST_HOST);
exports.config = {
tests: './tests/e2e/codecept/features/*.ts',
output: './tests/e2e/codecept/output',
helpers: {
TestCafe: {
url: process.env.BASE_URL || 'http://localhost:3000',
waitForTimeout: 3000,
show: true,
browser: 'chrome',
}
},
include: {},
bootstrap: null,
mocha: {},
name: 'test',
};
It is weird, indeed.
I'm seeing same kind of behaviour using Playwright, while I am not able to find a timeout: 0 as written in TestCafe.js
Have you confirmed that your element #username is really not on your page ?
I mean, this:
I.waitForElement('#username');
could be replaced by
I.click('#username');
just to force the focus on your field?
This is not a solution, but a potential (slightly better) workaround.
Closed for now! Feel free to reopen if you still encounter the issue with latest version and would be nice to provide a sample code to reproduce the issue.