Load of an IFrame that has an immediately submitted form.
The submitted form invokes the TestCafe driver _onFormSubmit() which gets an error
Cannot read property 'getItem' of null which in turn causes the submit to fail.
The submitted form completes successfully
As there isn't a ready set of code that can be extracted, I debugged TestCafe to find out where the issue is and it appears a simple enough race condition.
driver.js sets up the _onFormSubmit handler synchronously in the constructor
hammerhead.on(hammerhead.EVENTS.uncaughtJsError, err => this._onJsError(err));
hammerhead.on(hammerhead.EVENTS.unhandledRejection, err => this._onJsError(err));
hammerhead.on(hammerhead.EVENTS.consoleMethCalled, e => this._onConsoleMessage(e));
hammerhead.on(hammerhead.EVENTS.beforeFormSubmit, e => this._onFormSubmit(e));
but although iframe.driver.mustache calls the driver.start() synchronously
var IframeDriver = window['%testCafeIframeDriver%'];
var driver = new IframeDriver({{{testRunId}}}, {
selectorTimeout: {{{selectorTimeout}}},
pageLoadTimeout: {{{pageLoadTimeout}}},
dialogHandler: {{{dialogHandler}}},
unstableNetworkMode: {{{retryTestPages}}},
speed: {{{speed}}}
});
driver.start();
the iframe-driver.js implementation loads the contextStorage on a promise
start () {
this.nativeDialogsTracker = new IframeNativeDialogTracker(this.dialogHandler);
this.statusBar = new IframeStatusBar();
const initializePromise = this.parentDriverLink
.establishConnection()
.then(id => {
this.contextStorage = new ContextStorage(window, id);
if (this._failIfClientCodeExecutionIsInterrupted())
return;
const inCommandExecution = this.contextStorage.getItem(this.COMMAND_EXECUTING_FLAG) ||
this.contextStorage.getItem(this.EXECUTING_IN_IFRAME_FLAG);
if (inCommandExecution) {
this.contextStorage.setItem(this.COMMAND_EXECUTING_FLAG, false);
this.contextStorage.setItem(this.EXECUTING_IN_IFRAME_FLAG, false);
this._onReady(new DriverStatus({ isCommandResult: true }));
}
});
this.readyPromise = Promise.all([this.readyPromise, initializePromise]);
}
meanwhile any event that is triggered before the above promise will have a null contextStorage, and this indeed happens when the _onFormSubmit() is called as it assumes the presence of contextStorage. As you can see, this code is actually only present as a result of Issue #3560
// HACK: For https://github.com/DevExpress/testcafe/issues/3560
// We have to cancel every form submit after a test is done
// to prevent requests to a closed session
_onFormSubmit (e) {
if (this.contextStorage.getItem(TEST_DONE_SENT_FLAG))
e.preventSubmit = true;
}
As the Iframe driver needs the id so can't easily be synchronous, then the _onFormSubmit() (and similar) need a chick that contextStorage isn't null.
Fix has been included in this pull request -> https://github.com/DevExpress/testcafe/pull/4364
Thank you for your detailed research. My colleagues will also check your PR as soon as possible.
Hi guys, do you have an ETA on the PR related to this issue making it into a release version?
@bennymeade
Hi, we will accept that PR after the 1.6.1. version is released
Closed by #4364.
This thread has been automatically locked since it is closed and there has not been any recent activity. Please open a new issue for related bugs or feature requests. We recommend you ask TestCafe API, usage and configuration inquiries on StackOverflow.
Most helpful comment
@bennymeade
Hi, we will accept that PR after the 1.6.1. version is released