/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

// Test that console command input is persisted across toolbox loads.
// See Bug 943306.

"use strict";

requestLongerTimeout(2);

const TEST_URI = "data:text/html;charset=utf-8,Web Console test for " +
                 "persisting history - bug 943306";
const INPUT_HISTORY_COUNT = 10;

add_task(function* () {
  info("Setting custom input history pref to " + INPUT_HISTORY_COUNT);
  Services.prefs.setIntPref("devtools.webconsole.inputHistoryCount",
                            INPUT_HISTORY_COUNT);

  // First tab: run a bunch of commands and then make sure that you can
  // navigate through their history.
  yield loadTab(TEST_URI);
  let hud1 = yield openConsole();
  is(JSON.stringify(hud1.jsterm.history), "[]",
     "No history on first tab initially");
  yield populateInputHistory(hud1);
  is(JSON.stringify(hud1.jsterm.history),
     '["0","1","2","3","4","5","6","7","8","9"]',
     "First tab has populated history");

  // Second tab: Just make sure that you can navigate through the history
  // generated by the first tab.
  yield loadTab(TEST_URI);
  let hud2 = yield openConsole();
  is(JSON.stringify(hud2.jsterm.history),
     '["0","1","2","3","4","5","6","7","8","9"]',
     "Second tab has populated history");
  yield testNaviatingHistoryInUI(hud2);
  is(JSON.stringify(hud2.jsterm.history),
     '["0","1","2","3","4","5","6","7","8","9",""]',
     "An empty entry has been added in the second tab due to history perusal");

  // Third tab: Should have the same history as first tab, but if we run a
  // command, then the history of the first and second shouldn't be affected
  yield loadTab(TEST_URI);
  let hud3 = yield openConsole();
  is(JSON.stringify(hud3.jsterm.history),
     '["0","1","2","3","4","5","6","7","8","9"]',
     "Third tab has populated history");

  // Set input value separately from execute so UP arrow accurately navigates
  // history.
  hud3.jsterm.setInputValue('"hello from third tab"');
  yield hud3.jsterm.execute();

  is(JSON.stringify(hud1.jsterm.history),
     '["0","1","2","3","4","5","6","7","8","9"]',
     "First tab history hasn't changed due to command in third tab");
  is(JSON.stringify(hud2.jsterm.history),
     '["0","1","2","3","4","5","6","7","8","9",""]',
     "Second tab history hasn't changed due to command in third tab");
  is(JSON.stringify(hud3.jsterm.history),
     '["1","2","3","4","5","6","7","8","9","\\"hello from third tab\\""]',
     "Third tab has updated history (and purged the first result) after " +
     "running a command");

  // Fourth tab: Should have the latest command from the third tab, followed
  // by the rest of the history from the first tab.
  yield loadTab(TEST_URI);
  let hud4 = yield openConsole();
  is(JSON.stringify(hud4.jsterm.history),
     '["1","2","3","4","5","6","7","8","9","\\"hello from third tab\\""]',
     "Fourth tab has most recent history");

  yield hud4.jsterm.clearHistory();
  is(JSON.stringify(hud4.jsterm.history), "[]",
     "Clearing history for a tab works");

  yield loadTab(TEST_URI);
  let hud5 = yield openConsole();
  is(JSON.stringify(hud5.jsterm.history), "[]",
     "Clearing history carries over to a new tab");

  info("Clearing custom input history pref");
  Services.prefs.clearUserPref("devtools.webconsole.inputHistoryCount");
});

/**
 * Populate the history by running the following commands:
 *  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 */
function* populateInputHistory(hud) {
  let jsterm = hud.jsterm;

  for (let i = 0; i < INPUT_HISTORY_COUNT; i++) {
    // Set input value separately from execute so UP arrow accurately navigates
    // history.
    jsterm.setInputValue(i);
    yield jsterm.execute();
  }
}

/**
 * Check pressing up results in history traversal like:
 *  [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
 */
function* testNaviatingHistoryInUI(hud) {
  let jsterm = hud.jsterm;
  jsterm.focus();

  // Count backwards from original input and make sure that pressing up
  // restores this.
  for (let i = INPUT_HISTORY_COUNT - 1; i >= 0; i--) {
    EventUtils.synthesizeKey("KEY_ArrowUp");
    is(jsterm.getInputValue(), i, "Pressing up restores last input");
  }
}
