11cb0ef41Sopenharmony_ci/** 21cb0ef41Sopenharmony_ci * Supports pseudo-"namespacing" for window-posted messages for a given test 31cb0ef41Sopenharmony_ci * by generating and using a unique prefix that gets wrapped into message 41cb0ef41Sopenharmony_ci * objects. This makes it more feasible to have multiple tests that use 51cb0ef41Sopenharmony_ci * `window.postMessage` in a single test file. Basically, make it possible 61cb0ef41Sopenharmony_ci * for the each test to listen for only the messages that are pertinent to it. 71cb0ef41Sopenharmony_ci * 81cb0ef41Sopenharmony_ci * 'Prefix' not an elegant term to use here but this models itself after 91cb0ef41Sopenharmony_ci * PrefixedLocalStorage. 101cb0ef41Sopenharmony_ci * 111cb0ef41Sopenharmony_ci * PrefixedMessageTest: Instantiate in testharness.js tests to generate 121cb0ef41Sopenharmony_ci * a new unique-ish prefix that can be used by other test support files 131cb0ef41Sopenharmony_ci * PrefixedMessageResource: Instantiate in supporting test resource 141cb0ef41Sopenharmony_ci * files to use/share a prefix generated by a test. 151cb0ef41Sopenharmony_ci */ 161cb0ef41Sopenharmony_civar PrefixedMessage = function () { 171cb0ef41Sopenharmony_ci this.prefix = ''; 181cb0ef41Sopenharmony_ci this.param = 'prefixedMessage'; // Param to use in querystrings 191cb0ef41Sopenharmony_ci}; 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci/** 221cb0ef41Sopenharmony_ci * Generate a URL that adds/replaces param with this object's prefix 231cb0ef41Sopenharmony_ci * Use to link to test support files that make use of 241cb0ef41Sopenharmony_ci * PrefixedMessageResource. 251cb0ef41Sopenharmony_ci */ 261cb0ef41Sopenharmony_ciPrefixedMessage.prototype.url = function (uri) { 271cb0ef41Sopenharmony_ci function updateUrlParameter (uri, key, value) { 281cb0ef41Sopenharmony_ci var i = uri.indexOf('#'); 291cb0ef41Sopenharmony_ci var hash = (i === -1) ? '' : uri.substr(i); 301cb0ef41Sopenharmony_ci uri = (i === -1) ? uri : uri.substr(0, i); 311cb0ef41Sopenharmony_ci var re = new RegExp(`([?&])${key}=.*?(&|$)`, 'i'); 321cb0ef41Sopenharmony_ci var separator = uri.indexOf('?') !== -1 ? '&' : '?'; 331cb0ef41Sopenharmony_ci uri = (uri.match(re)) ? uri.replace(re, `$1${key}=${value}$2`) : 341cb0ef41Sopenharmony_ci `${uri}${separator}${key}=${value}`; 351cb0ef41Sopenharmony_ci return uri + hash; 361cb0ef41Sopenharmony_ci } 371cb0ef41Sopenharmony_ci return updateUrlParameter(uri, this.param, this.prefix); 381cb0ef41Sopenharmony_ci}; 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci/** 411cb0ef41Sopenharmony_ci * Add an eventListener on `message` but only invoke the given callback 421cb0ef41Sopenharmony_ci * for messages whose object contains this object's prefix. Remove the 431cb0ef41Sopenharmony_ci * event listener once the anticipated message has been received. 441cb0ef41Sopenharmony_ci */ 451cb0ef41Sopenharmony_ciPrefixedMessage.prototype.onMessage = function (fn) { 461cb0ef41Sopenharmony_ci window.addEventListener('message', e => { 471cb0ef41Sopenharmony_ci if (typeof e.data === 'object' && e.data.hasOwnProperty('prefix')) { 481cb0ef41Sopenharmony_ci if (e.data.prefix === this.prefix) { 491cb0ef41Sopenharmony_ci // Only invoke callback when `data` is an object containing 501cb0ef41Sopenharmony_ci // a `prefix` key with this object's prefix value 511cb0ef41Sopenharmony_ci // Note fn is invoked with "unwrapped" data first, then the event `e` 521cb0ef41Sopenharmony_ci // (which contains the full, wrapped e.data should it be needed) 531cb0ef41Sopenharmony_ci fn.call(this, e.data.data, e); 541cb0ef41Sopenharmony_ci window.removeEventListener('message', fn); 551cb0ef41Sopenharmony_ci } 561cb0ef41Sopenharmony_ci } 571cb0ef41Sopenharmony_ci }); 581cb0ef41Sopenharmony_ci}; 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci/** 611cb0ef41Sopenharmony_ci * Instantiate in a test file (e.g. during `setup`) to create a unique-ish 621cb0ef41Sopenharmony_ci * prefix that can be shared by support files 631cb0ef41Sopenharmony_ci */ 641cb0ef41Sopenharmony_civar PrefixedMessageTest = function () { 651cb0ef41Sopenharmony_ci PrefixedMessage.call(this); 661cb0ef41Sopenharmony_ci this.prefix = `${document.location.pathname}-${Math.random()}-${Date.now()}-`; 671cb0ef41Sopenharmony_ci}; 681cb0ef41Sopenharmony_ciPrefixedMessageTest.prototype = Object.create(PrefixedMessage.prototype); 691cb0ef41Sopenharmony_ciPrefixedMessageTest.prototype.constructor = PrefixedMessageTest; 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci/** 721cb0ef41Sopenharmony_ci * Instantiate in a test support script to use a "prefix" generated by a 731cb0ef41Sopenharmony_ci * PrefixedMessageTest in a controlling test file. It will look for 741cb0ef41Sopenharmony_ci * the prefix in a URL param (see also PrefixedMessage#url) 751cb0ef41Sopenharmony_ci */ 761cb0ef41Sopenharmony_civar PrefixedMessageResource = function () { 771cb0ef41Sopenharmony_ci PrefixedMessage.call(this); 781cb0ef41Sopenharmony_ci // Check URL querystring for prefix to use 791cb0ef41Sopenharmony_ci var regex = new RegExp(`[?&]${this.param}(=([^&#]*)|&|#|$)`), 801cb0ef41Sopenharmony_ci results = regex.exec(document.location.href); 811cb0ef41Sopenharmony_ci if (results && results[2]) { 821cb0ef41Sopenharmony_ci this.prefix = results[2]; 831cb0ef41Sopenharmony_ci } 841cb0ef41Sopenharmony_ci}; 851cb0ef41Sopenharmony_ciPrefixedMessageResource.prototype = Object.create(PrefixedMessage.prototype); 861cb0ef41Sopenharmony_ciPrefixedMessageResource.prototype.constructor = PrefixedMessageResource; 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci/** 891cb0ef41Sopenharmony_ci * This is how a test resource document can "send info" to its 901cb0ef41Sopenharmony_ci * opener context. It will whatever message is being sent (`data`) in 911cb0ef41Sopenharmony_ci * an object that injects the prefix. 921cb0ef41Sopenharmony_ci */ 931cb0ef41Sopenharmony_ciPrefixedMessageResource.prototype.postToOpener = function (data) { 941cb0ef41Sopenharmony_ci if (window.opener) { 951cb0ef41Sopenharmony_ci window.opener.postMessage({ 961cb0ef41Sopenharmony_ci prefix: this.prefix, 971cb0ef41Sopenharmony_ci data: data 981cb0ef41Sopenharmony_ci }, '*'); 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci}; 101