summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/common/PrefixedPostMessage.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/common/PrefixedPostMessage.js')
-rw-r--r--testing/web-platform/tests/common/PrefixedPostMessage.js100
1 files changed, 100 insertions, 0 deletions
diff --git a/testing/web-platform/tests/common/PrefixedPostMessage.js b/testing/web-platform/tests/common/PrefixedPostMessage.js
new file mode 100644
index 0000000000..674b52877c
--- /dev/null
+++ b/testing/web-platform/tests/common/PrefixedPostMessage.js
@@ -0,0 +1,100 @@
+/**
+ * Supports pseudo-"namespacing" for window-posted messages for a given test
+ * by generating and using a unique prefix that gets wrapped into message
+ * objects. This makes it more feasible to have multiple tests that use
+ * `window.postMessage` in a single test file. Basically, make it possible
+ * for the each test to listen for only the messages that are pertinent to it.
+ *
+ * 'Prefix' not an elegant term to use here but this models itself after
+ * PrefixedLocalStorage.
+ *
+ * PrefixedMessageTest: Instantiate in testharness.js tests to generate
+ * a new unique-ish prefix that can be used by other test support files
+ * PrefixedMessageResource: Instantiate in supporting test resource
+ * files to use/share a prefix generated by a test.
+ */
+var PrefixedMessage = function () {
+ this.prefix = '';
+ this.param = 'prefixedMessage'; // Param to use in querystrings
+};
+
+/**
+ * Generate a URL that adds/replaces param with this object's prefix
+ * Use to link to test support files that make use of
+ * PrefixedMessageResource.
+ */
+PrefixedMessage.prototype.url = function (uri) {
+ function updateUrlParameter (uri, key, value) {
+ var i = uri.indexOf('#');
+ var hash = (i === -1) ? '' : uri.substr(i);
+ uri = (i === -1) ? uri : uri.substr(0, i);
+ var re = new RegExp(`([?&])${key}=.*?(&|$)`, 'i');
+ var separator = uri.indexOf('?') !== -1 ? '&' : '?';
+ uri = (uri.match(re)) ? uri.replace(re, `$1${key}=${value}$2`) :
+ `${uri}${separator}${key}=${value}`;
+ return uri + hash;
+ }
+ return updateUrlParameter(uri, this.param, this.prefix);
+};
+
+/**
+ * Add an eventListener on `message` but only invoke the given callback
+ * for messages whose object contains this object's prefix. Remove the
+ * event listener once the anticipated message has been received.
+ */
+PrefixedMessage.prototype.onMessage = function (fn) {
+ window.addEventListener('message', e => {
+ if (typeof e.data === 'object' && e.data.hasOwnProperty('prefix')) {
+ if (e.data.prefix === this.prefix) {
+ // Only invoke callback when `data` is an object containing
+ // a `prefix` key with this object's prefix value
+ // Note fn is invoked with "unwrapped" data first, then the event `e`
+ // (which contains the full, wrapped e.data should it be needed)
+ fn.call(this, e.data.data, e);
+ window.removeEventListener('message', fn);
+ }
+ }
+ });
+};
+
+/**
+ * Instantiate in a test file (e.g. during `setup`) to create a unique-ish
+ * prefix that can be shared by support files
+ */
+var PrefixedMessageTest = function () {
+ PrefixedMessage.call(this);
+ this.prefix = `${document.location.pathname}-${Math.random()}-${Date.now()}-`;
+};
+PrefixedMessageTest.prototype = Object.create(PrefixedMessage.prototype);
+PrefixedMessageTest.prototype.constructor = PrefixedMessageTest;
+
+/**
+ * Instantiate in a test support script to use a "prefix" generated by a
+ * PrefixedMessageTest in a controlling test file. It will look for
+ * the prefix in a URL param (see also PrefixedMessage#url)
+ */
+var PrefixedMessageResource = function () {
+ PrefixedMessage.call(this);
+ // Check URL querystring for prefix to use
+ var regex = new RegExp(`[?&]${this.param}(=([^&#]*)|&|#|$)`),
+ results = regex.exec(document.location.href);
+ if (results && results[2]) {
+ this.prefix = results[2];
+ }
+};
+PrefixedMessageResource.prototype = Object.create(PrefixedMessage.prototype);
+PrefixedMessageResource.prototype.constructor = PrefixedMessageResource;
+
+/**
+ * This is how a test resource document can "send info" to its
+ * opener context. It will whatever message is being sent (`data`) in
+ * an object that injects the prefix.
+ */
+PrefixedMessageResource.prototype.postToOpener = function (data) {
+ if (window.opener) {
+ window.opener.postMessage({
+ prefix: this.prefix,
+ data: data
+ }, '*');
+ }
+};