"use strict";

/**
 * Helpers for use in tests that want to verify that localized error messages
 * are logged during the test.  Because most of our errors (ex:
 * ServiceWorkerManager) generate nsIScriptError instances with flattened
 * strings (the interpolated arguments aren't kept around), we load the string
 * bundle and use it to derive the exact string message we expect for the given
 * payload.
 **/

let stringBundleService =
  SpecialPowers.Cc["@mozilla.org/intl/stringbundle;1"]
               .getService(SpecialPowers.Ci.nsIStringBundleService);
let localizer =
  stringBundleService.createBundle("chrome://global/locale/dom/dom.properties");

/**
 * Start monitoring the console for the given localized error message string(s)
 * with the given arguments to be logged.  Call before running code that will
 * generate the console message.  Pair with a call to
 * `wait_for_expected_message` invoked after the message should have been
 * generated.
 *
 * Multiple error messages can be expected, just repeat the msgId and args
 * argument pair as needed.
 *
 * @param {String} msgId
 *   The localization message identifier used in the properties file.
 * @param {String[]} args
 *   The list of formatting arguments we expect the error to be generated with.
 * @return {Object} Promise/handle to pass to wait_for_expected_message.
 */
function expect_console_message(/* msgId, args, ... */) {
  let expectations = [];
  // process repeated paired arguments of: msgId, args
  for (let i = 0; i < arguments.length; i += 2) {
    let msgId = arguments[i];
    let args = arguments[i + 1];
    if (args.length === 0) {
      expectations.push({errorMessage: localizer.GetStringFromName(msgId)});
    } else {
      expectations.push({
        errorMessage: localizer.formatStringFromName(msgId, args, args.length)
      });
    }
  }
  return new Promise(resolve => {
    SimpleTest.monitorConsole(resolve, expectations);
  });
}
let expect_console_messages = expect_console_message;

/**
 * Stop monitoring the console, returning a Promise that will be resolved when
 * the sentinel console message sent through the async data path has been
 * received.  The Promise will not reject on failure; instead a mochitest
 * failure will have been generated by ok(false)/equivalent by the time it is
 * resolved.
 */
function wait_for_expected_message(expectedPromise) {
  SimpleTest.endMonitorConsole();
  return expectedPromise;
}

/**
 * Derive an absolute URL string from a relative URL to simplify error message
 * argument generation.
 */
function make_absolute_url(relUrl) {
  return new URL(relUrl, window.location).href;
}
