diff --git a/gulp/constants/functional-test-globs.js b/gulp/constants/functional-test-globs.js
index 30103dab84d..282ca6025ed 100644
--- a/gulp/constants/functional-test-globs.js
+++ b/gulp/constants/functional-test-globs.js
@@ -42,6 +42,7 @@ const PROXYLESS_TESTS_GLOB = [
'test/functional/fixtures/api/es-next/console/test.js',
'test/functional/fixtures/api/es-next/roles/test.js',
'test/functional/fixtures/request-pipeline/**/test.js',
+ 'test/functional/fixtures/hammerhead/worker/test.js',
];
module.exports = {
diff --git a/package.json b/package.json
index de0ba599f40..e7f01583cb4 100644
--- a/package.json
+++ b/package.json
@@ -139,7 +139,7 @@
"source-map-support": "^0.5.16",
"strip-bom": "^2.0.0",
"testcafe-browser-tools": "2.0.23",
- "testcafe-hammerhead": "28.2.2",
+ "testcafe-hammerhead": "28.2.3",
"testcafe-legacy-api": "5.1.6",
"testcafe-reporter-dashboard": "^0.2.8",
"testcafe-reporter-json": "^2.1.0",
diff --git a/test/functional/fixtures/api/es-next/iframe-switching/pages/message-event/cross-domain.html b/test/functional/fixtures/api/es-next/iframe-switching/pages/message-event/cross-domain.html
new file mode 100644
index 00000000000..c69ed6d7e9a
--- /dev/null
+++ b/test/functional/fixtures/api/es-next/iframe-switching/pages/message-event/cross-domain.html
@@ -0,0 +1,40 @@
+
+
+
+
+ Cross-domain page
+
+
+ Cross-domain page
+
+
+ Interactions
+
+
+
+
+
diff --git a/test/functional/fixtures/api/es-next/iframe-switching/pages/message-event/index.html b/test/functional/fixtures/api/es-next/iframe-switching/pages/message-event/index.html
new file mode 100644
index 00000000000..13de70e5efd
--- /dev/null
+++ b/test/functional/fixtures/api/es-next/iframe-switching/pages/message-event/index.html
@@ -0,0 +1,45 @@
+
+
+
+
+ Index Page
+
+
+ Index Page
+
+
+
+
+
+
+
+
+
diff --git a/test/functional/fixtures/api/es-next/iframe-switching/test.js b/test/functional/fixtures/api/es-next/iframe-switching/test.js
index 4b697257667..64dda4b2880 100644
--- a/test/functional/fixtures/api/es-next/iframe-switching/test.js
+++ b/test/functional/fixtures/api/es-next/iframe-switching/test.js
@@ -74,6 +74,10 @@ describe('[API] t.switchToIframe(), t.switchToMainWindow()', function () {
return runTests('./testcafe-fixtures/iframe-switching-test.js', 'Click in an iframe with the srcdoc attribute', { skip: 'ie', ...DEFAULT_RUN_OPTIONS });
});
+ it('Correct execution order of "message" events in cross-domain iframe', function () {
+ return runTests('./testcafe-fixtures/message-event.js', null, { skip: 'ie', ...DEFAULT_RUN_OPTIONS });
+ });
+
describe('Unavailable iframe errors', function () {
it('Should ensure the iframe element exists before switching to it', function () {
return runTests('./testcafe-fixtures/iframe-switching-test.js', 'Switch to a non-existent iframe',
diff --git a/test/functional/fixtures/api/es-next/iframe-switching/testcafe-fixtures/message-event.js b/test/functional/fixtures/api/es-next/iframe-switching/testcafe-fixtures/message-event.js
new file mode 100644
index 00000000000..0a8cc482ea3
--- /dev/null
+++ b/test/functional/fixtures/api/es-next/iframe-switching/testcafe-fixtures/message-event.js
@@ -0,0 +1,20 @@
+import { Selector } from 'testcafe';
+
+fixture `Message Event`
+ .page('http://localhost:3000/fixtures/api/es-next/iframe-switching/pages/message-event/index.html');
+
+test('test', async t => {
+ const receivedLog = Selector('#received-log').addCustomDOMProperties({
+ trimmedInnerText: el => el.innerText.replace('\n', ''),
+ });
+
+ await t
+ .click('#post-string-message')
+ .click('#post-object-message')
+ .expect(receivedLog.trimmedInnerText).eql('"string message processed"{"object":"message","processed":true}')
+ .switchToIframe('#cross-domain-iframe')
+ .expect(receivedLog.trimmedInnerText).eql('"string message"{"object":"message"}')
+ .typeText('#input', 'Text')
+ .expect(Selector('#input').value).eql('Text')
+ .switchToMainWindow();
+});
diff --git a/test/functional/fixtures/hammerhead/worker/pages/index.html b/test/functional/fixtures/hammerhead/worker/pages/index.html
new file mode 100644
index 00000000000..ff805b99173
--- /dev/null
+++ b/test/functional/fixtures/hammerhead/worker/pages/index.html
@@ -0,0 +1,34 @@
+
+
+
+
+ Worker
+
+
+ Worker
+
+ * =
+
+
+
+
diff --git a/test/functional/fixtures/hammerhead/worker/pages/worker.js b/test/functional/fixtures/hammerhead/worker/pages/worker.js
new file mode 100644
index 00000000000..033d87628ee
--- /dev/null
+++ b/test/functional/fixtures/hammerhead/worker/pages/worker.js
@@ -0,0 +1,5 @@
+onmessage = function (e) {
+ const result = parseInt(e.data.first, 10) * parseInt(e.data.second, 10);
+
+ postMessage(isNaN(result) ? '' : result);
+};
diff --git a/test/functional/fixtures/hammerhead/worker/test.js b/test/functional/fixtures/hammerhead/worker/test.js
new file mode 100644
index 00000000000..d89edd24482
--- /dev/null
+++ b/test/functional/fixtures/hammerhead/worker/test.js
@@ -0,0 +1,5 @@
+describe('Worker', function () {
+ it('Basic Worker', function () {
+ return runTests('testcafe-fixtures/index.js', null, { skip: 'ie' });
+ });
+});
diff --git a/test/functional/fixtures/hammerhead/worker/testcafe-fixtures/index.js b/test/functional/fixtures/hammerhead/worker/testcafe-fixtures/index.js
new file mode 100644
index 00000000000..8ab63c013c5
--- /dev/null
+++ b/test/functional/fixtures/hammerhead/worker/testcafe-fixtures/index.js
@@ -0,0 +1,11 @@
+import { Selector } from 'testcafe';
+
+fixture `Worker`
+ .page `http://localhost:3000/fixtures/hammerhead/worker/pages/index.html`;
+
+test('test', async t => {
+ await t
+ .typeText('#first', '2')
+ .typeText('#second', '3')
+ .expect(Selector('#result').value).eql('6');
+});