import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,13 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'scratchpad-commands.js',
'scratchpad-manager.jsm',
'scratchpad-panel.js',
)
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']

View file

@ -0,0 +1,22 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const l10n = require("gcli/l10n");
const {Cu} = require("chrome");
exports.items = [{
item: "command",
runAt: "client",
name: "scratchpad",
buttonId: "command-button-scratchpad",
buttonClass: "command-button command-button-invertable",
tooltipText: l10n.lookup("scratchpadOpenTooltip"),
hidden: true,
exec: function (args, context) {
const {ScratchpadManager} = Cu.import("resource://devtools/client/scratchpad/scratchpad-manager.jsm", {});
ScratchpadManager.openScratchpad();
}
}];

View file

@ -0,0 +1,185 @@
/* vim:set ts=2 sw=2 sts=2 et tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = ["ScratchpadManager"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const SCRATCHPAD_WINDOW_URL = "chrome://devtools/content/scratchpad/scratchpad.xul";
const SCRATCHPAD_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
const Services = require("Services");
const Telemetry = require("devtools/client/shared/telemetry");
/**
* The ScratchpadManager object opens new Scratchpad windows and manages the state
* of open scratchpads for session restore. There's only one ScratchpadManager in
* the life of the browser.
*/
this.ScratchpadManager = {
_nextUid: 1,
_scratchpads: [],
_telemetry: new Telemetry(),
/**
* Get the saved states of open scratchpad windows. Called by
* session restore.
*
* @return array
* The array of scratchpad states.
*/
getSessionState: function SPM_getSessionState()
{
return this._scratchpads;
},
/**
* Restore scratchpad windows from the scratchpad session store file.
* Called by session restore.
*
* @param function aSession
* The session object with scratchpad states.
*
* @return array
* The restored scratchpad windows.
*/
restoreSession: function SPM_restoreSession(aSession)
{
if (!Array.isArray(aSession)) {
return [];
}
let wins = [];
aSession.forEach(function (state) {
let win = this.openScratchpad(state);
wins.push(win);
}, this);
return wins;
},
/**
* Iterate through open scratchpad windows and save their states.
*/
saveOpenWindows: function SPM_saveOpenWindows() {
this._scratchpads = [];
function clone(src) {
let dest = {};
for (let key in src) {
if (src.hasOwnProperty(key)) {
dest[key] = src[key];
}
}
return dest;
}
// We need to clone objects we get from Scratchpad instances
// because such (cross-window) objects have a property 'parent'
// that holds on to a ChromeWindow instance. This means that
// such objects are not primitive-values-only anymore so they
// can leak.
let enumerator = Services.wm.getEnumerator("devtools:scratchpad");
while (enumerator.hasMoreElements()) {
let win = enumerator.getNext();
if (!win.closed && win.Scratchpad.initialized) {
this._scratchpads.push(clone(win.Scratchpad.getState()));
}
}
},
/**
* Open a new scratchpad window with an optional initial state.
*
* @param object aState
* Optional. The initial state of the scratchpad, an object
* with properties filename, text, and executionContext.
*
* @return nsIDomWindow
* The opened scratchpad window.
*/
openScratchpad: function SPM_openScratchpad(aState)
{
let params = Cc["@mozilla.org/embedcomp/dialogparam;1"]
.createInstance(Ci.nsIDialogParamBlock);
params.SetNumberStrings(2);
params.SetString(0, this.createUid());
if (aState) {
if (typeof aState != "object") {
return;
}
params.SetString(1, JSON.stringify(aState));
}
let win = Services.ww.openWindow(null, SCRATCHPAD_WINDOW_URL, "_blank",
SCRATCHPAD_WINDOW_FEATURES, params);
this._telemetry.toolOpened("scratchpad-window");
let onClose = () => {
this._telemetry.toolClosed("scratchpad-window");
};
win.addEventListener("unload", onClose);
// Only add the shutdown observer if we've opened a scratchpad window.
ShutdownObserver.init();
return win;
},
/**
* Create a unique ID for a new Scratchpad.
*/
createUid: function SPM_createUid()
{
return JSON.stringify(this._nextUid++);
}
};
/**
* The ShutdownObserver listens for app shutdown and saves the current state
* of the scratchpads for session restore.
*/
var ShutdownObserver = {
_initialized: false,
init: function SDO_init()
{
if (this._initialized) {
return;
}
Services.obs.addObserver(this, "quit-application-granted", false);
this._initialized = true;
},
observe: function SDO_observe(aMessage, aTopic, aData)
{
if (aTopic == "quit-application-granted") {
ScratchpadManager.saveOpenWindows();
this.uninit();
}
},
uninit: function SDO_uninit()
{
Services.obs.removeObserver(this, "quit-application-granted");
}
};

View file

@ -0,0 +1,56 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {Cu} = require("chrome");
const EventEmitter = require("devtools/shared/event-emitter");
const promise = require("promise");
function ScratchpadPanel(iframeWindow, toolbox) {
let { Scratchpad } = iframeWindow;
this._toolbox = toolbox;
this.panelWin = iframeWindow;
this.scratchpad = Scratchpad;
Scratchpad.target = this.target;
Scratchpad.hideMenu();
let deferred = promise.defer();
this._readyObserver = deferred.promise;
Scratchpad.addObserver({
onReady: function () {
Scratchpad.removeObserver(this);
deferred.resolve();
}
});
EventEmitter.decorate(this);
}
exports.ScratchpadPanel = ScratchpadPanel;
ScratchpadPanel.prototype = {
/**
* Open is effectively an asynchronous constructor. For the ScratchpadPanel,
* by the time this is called, the Scratchpad will already be ready.
*/
open: function () {
return this._readyObserver.then(() => {
this.isReady = true;
this.emit("ready");
return this;
});
},
get target() {
return this._toolbox.target;
},
destroy: function () {
this.emit("destroyed");
return promise.resolve();
}
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,412 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE window [
<!ENTITY % scratchpadDTD SYSTEM "chrome://devtools/locale/scratchpad.dtd" >
%scratchpadDTD;
<!ENTITY % editMenuStrings SYSTEM "chrome://global/locale/editMenuOverlay.dtd">
%editMenuStrings;
<!ENTITY % sourceEditorStrings SYSTEM "chrome://devtools/locale/sourceeditor.dtd">
%sourceEditorStrings;
]>
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://devtools/skin/scratchpad.css"?>
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
<window id="main-window"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&window.title;"
windowtype="devtools:scratchpad"
macanimationtype="document"
fullscreenbutton="true"
screenX="4" screenY="4"
width="640" height="480"
persist="screenX screenY width height sizemode">
<script type="application/javascript;version=1.8"
src="chrome://devtools/content/shared/theme-switching.js"/>
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="application/javascript" src="chrome://devtools/content/scratchpad/scratchpad.js"/>
<commandset id="editMenuCommands"/>
<commandset id="sourceEditorCommands">
<command id="cmd_find" oncommand=";"/>
<command id="cmd_findAgain" oncommand=";"/>
<command id="cmd_gotoLine" oncommand=";"/>
</commandset>
<commandset id="sp-commandset">
<command id="sp-cmd-newWindow" oncommand=";"/>
<command id="sp-cmd-openFile" oncommand=";"/>
<command id="sp-cmd-clearRecentFiles" oncommand=";"/>
<command id="sp-cmd-save" oncommand=";"/>
<command id="sp-cmd-saveas" oncommand=";"/>
<command id="sp-cmd-revert" oncommand=";" disabled="true"/>
<command id="sp-cmd-close" oncommand=";"/>
<command id="sp-cmd-line-numbers" oncommand=";"/>
<command id="sp-cmd-wrap-text" oncommand=";"/>
<command id="sp-cmd-highlight-trailing-space" oncommand=";"/>
<command id="sp-cmd-larger-font" oncommand=";"/>
<command id="sp-cmd-smaller-font" oncommand=";"/>
<command id="sp-cmd-normal-font" oncommand=";"/>
<command id="sp-cmd-run" oncommand=";"/>
<command id="sp-cmd-inspect" oncommand=";"/>
<command id="sp-cmd-display" oncommand=";"/>
<command id="sp-cmd-pprint" oncommand=";"/>
<command id="sp-cmd-contentContext" oncommand=";"/>
<command id="sp-cmd-browserContext" oncommand=";" disabled="true"/>
<command id="sp-cmd-reloadAndRun" oncommand=";"/>
<command id="sp-cmd-evalFunction" oncommand=";"/>
<command id="sp-cmd-errorConsole" oncommand=";" disabled="true"/>
<command id="sp-cmd-webConsole" oncommand=";"/>
<command id="sp-cmd-documentationLink" oncommand=";"/>
<command id="sp-cmd-hideSidebar" oncommand=";"/>
</commandset>
<keyset id="editMenuKeys"/>
<keyset id="sp-keyset">
<key id="sp-key-window"
key="&newWindowCmd.commandkey;"
command="sp-cmd-newWindow"
modifiers="accel"/>
<key id="sp-key-open"
key="&openFileCmd.commandkey;"
command="sp-cmd-openFile"
modifiers="accel"/>
<key id="sp-key-save"
key="&saveFileCmd.commandkey;"
command="sp-cmd-save"
modifiers="accel"/>
<key id="sp-key-close"
key="&closeCmd.key;"
command="sp-cmd-close"
modifiers="accel"/>
<key id="sp-key-larger-font"
key="&largerFont.commandkey;"
command="sp-cmd-larger-font"
modifiers="accel"/>
<key key="&largerFont.commandkey2;"
command="sp-cmd-larger-font"
modifiers="accel"/>
<key id="sp-key-smaller-font"
key="&smallerFont.commandkey;"
command="sp-cmd-smaller-font"
modifiers="accel"/>
<key id="sp-key-normal-size-font"
key="&normalSize.commandkey;"
command="sp-cmd-normal-font"
modifiers="accel"/>
<key id="sp-key-run"
key="&run.key;"
command="sp-cmd-run"
modifiers="accel"/>
<key id="sp-key-inspect"
key="&inspect.key;"
command="sp-cmd-inspect"
modifiers="accel"/>
<key id="sp-key-display"
key="&display.key;"
command="sp-cmd-display"
modifiers="accel"/>
<key id="sp-key-pprint"
key="&pprint.key;"
command="sp-cmd-pprint"
modifiers="accel"/>
<key id="sp-key-reloadAndRun"
key="&reloadAndRun.key;"
command="sp-cmd-reloadAndRun"
modifiers="accel,shift"/>
<key id="sp-key-evalFunction"
key="&evalFunction.key;"
command="sp-cmd-evalFunction"
modifiers="accel"/>
<key id="sp-key-errorConsole"
key="&errorConsoleCmd.commandkey;"
command="sp-cmd-errorConsole"
modifiers="accel,shift"/>
<key id="sp-key-hideSidebar"
keycode="VK_ESCAPE"
command="sp-cmd-hideSidebar"/>
<key id="key_openHelp"
keycode="VK_F1"
command="sp-cmd-documentationLink"/>
<key id="key_gotoLine"
key="&gotoLineCmd.key;"
command="key_gotoLine"
modifiers="accel"/>
</keyset>
<menubar id="sp-menubar">
<menu id="sp-file-menu" label="&fileMenu.label;" accesskey="&fileMenu.accesskey;">
<menupopup id="sp-menu-filepopup">
<menuitem id="sp-menu-newscratchpad"
label="&newWindowCmd.label;"
accesskey="&newWindowCmd.accesskey;"
key="sp-key-window"
command="sp-cmd-newWindow"/>
<menuseparator/>
<menuitem id="sp-menu-open"
label="&openFileCmd.label;"
command="sp-cmd-openFile"
key="sp-key-open"
accesskey="&openFileCmd.accesskey;"/>
<menu id="sp-open_recent-menu" label="&openRecentMenu.label;"
accesskey="&openRecentMenu.accesskey;"
disabled="true">
<menupopup id="sp-menu-open_recentPopup"/>
</menu>
<menuitem id="sp-menu-save"
label="&saveFileCmd.label;"
accesskey="&saveFileCmd.accesskey;"
key="sp-key-save"
command="sp-cmd-save"/>
<menuitem id="sp-menu-saveas"
label="&saveFileAsCmd.label;"
accesskey="&saveFileAsCmd.accesskey;"
command="sp-cmd-saveas"/>
<menuitem id="sp-menu-revert"
label="&revertCmd.label;"
accesskey="&revertCmd.accesskey;"
command="sp-cmd-revert"/>
<menuseparator/>
<menuitem id="sp-menu-close"
label="&closeCmd.label;"
key="sp-key-close"
accesskey="&closeCmd.accesskey;"
command="sp-cmd-close"/>
</menupopup>
</menu>
<menu id="sp-edit-menu" label="&editMenu.label;"
accesskey="&editMenu.accesskey;">
<menupopup id="sp-menu_editpopup">
<menuitem id="menu_undo"/>
<menuitem id="menu_redo"/>
<menuseparator/>
<menuitem id="menu_cut"/>
<menuitem id="menu_copy"/>
<menuitem id="menu_paste"/>
<menuseparator/>
<menuitem id="menu_selectAll"/>
<menuseparator/>
<menuitem id="menu_find"/>
<menuitem id="menu_findAgain"/>
<menuseparator/>
<menuitem id="se-menu-gotoLine"
label="&gotoLineCmd.label;"
accesskey="&gotoLineCmd.accesskey;"
key="key_gotoLine"
command="cmd_gotoLine"/>
<menuitem id="sp-menu-pprint"
label="&pprint.label;"
accesskey="&pprint.accesskey;"
key="sp-key-pprint"
command="sp-cmd-pprint"/>
</menupopup>
</menu>
<menu id="sp-view-menu" label="&viewMenu.label;" accesskey="&viewMenu.accesskey;">
<menupopup id="sp-menu-viewpopup">
<menuitem id="sp-menu-line-numbers"
label="&lineNumbers.label;"
accesskey="&lineNumbers.accesskey;"
type="checkbox"
command="sp-cmd-line-numbers"/>
<menuitem id="sp-menu-word-wrap"
label="&wordWrap.label;"
accesskey="&wordWrap.accesskey;"
type="checkbox"
command="sp-cmd-wrap-text"/>
<menuitem id="sp-menu-highlight-trailing-space"
label="&highlightTrailingSpace.label;"
accesskey="&highlightTrailingSpace.accesskey;"
type="checkbox"
command="sp-cmd-highlight-trailing-space"/>
<menuseparator/>
<menuitem id="sp-menu-larger-font"
label="&largerFont.label;"
key="sp-key-larger-font"
accesskey="&largerFont.accesskey;"
command="sp-cmd-larger-font"/>
<menuitem id="sp-menu-smaller-font"
label="&smallerFont.label;"
key="sp-key-smaller-font"
accesskey="&smallerFont.accesskey;"
command="sp-cmd-smaller-font"/>
<menuitem id="sp-menu-normal-size-font"
label="&normalSize.label;"
key="sp-menu-normal-font"
accesskey="&normalSize.accesskey;"
command="sp-cmd-normal-font"/>
</menupopup>
</menu>
<menu id="sp-execute-menu" label="&executeMenu.label;"
accesskey="&executeMenu.accesskey;">
<menupopup id="sp-menu_executepopup">
<menuitem id="sp-text-run"
label="&run.label;"
accesskey="&run.accesskey;"
key="sp-key-run"
command="sp-cmd-run"/>
<menuitem id="sp-text-inspect"
label="&inspect.label;"
accesskey="&inspect.accesskey;"
key="sp-key-inspect"
command="sp-cmd-inspect"/>
<menuitem id="sp-text-display"
label="&display.label;"
accesskey="&display.accesskey;"
key="sp-key-display"
command="sp-cmd-display"/>
<menuseparator/>
<menuitem id="sp-text-reloadAndRun"
label="&reloadAndRun.label;"
key="sp-key-reloadAndRun"
accesskey="&reloadAndRun.accesskey;"
command="sp-cmd-reloadAndRun"/>
<menuitem id="sp-text-evalFunction"
label="&evalFunction.label;"
key="sp-key-evalFunction"
accesskey="&evalFunction.accesskey;"
command="sp-cmd-evalFunction"/>
</menupopup>
</menu>
<menu id="sp-environment-menu"
label="&environmentMenu.label;"
accesskey="&environmentMenu.accesskey;"
hidden="true">
<menupopup id="sp-menu-environment">
<menuitem id="sp-menu-content"
label="&contentContext.label;"
accesskey="&contentContext.accesskey;"
command="sp-cmd-contentContext"
checked="true"
type="radio"/>
<menuitem id="sp-menu-browser"
command="sp-cmd-browserContext"
label="&browserContext.label;"
accesskey="&browserContext.accesskey;"
type="radio"/>
</menupopup>
</menu>
#ifdef XP_WIN
<menu id="sp-help-menu"
label="&helpMenu.label;"
accesskey="&helpMenuWin.accesskey;">
#else
<menu id="sp-help-menu"
label="&helpMenu.label;"
accesskey="&helpMenu.accesskey;">
#endif
<menupopup id="sp-menu-help">
<menuitem id="sp-menu-documentation"
label="&documentationLink.label;"
accesskey="&documentationLink.accesskey;"
command="sp-cmd-documentationLink"
key="key_openHelp"/>
</menupopup>
</menu>
</menubar>
<toolbar id="sp-toolbar"
class="devtools-toolbar">
<toolbarbutton id="sp-toolbar-open"
class="devtools-toolbarbutton"
label="&openFileCmd.label;"
command="sp-cmd-openFile"/>
<toolbarbutton id="sp-toolbar-save"
class="devtools-toolbarbutton"
label="&saveFileCmd.label;"
command="sp-cmd-save"/>
<toolbarbutton id="sp-toolbar-saveAs"
class="devtools-toolbarbutton"
label="&saveFileAsCmd.label;"
command="sp-cmd-saveas"/>
<toolbarspacer/>
<toolbarbutton id="sp-toolbar-run"
class="devtools-toolbarbutton"
label="&run.label;"
command="sp-cmd-run"/>
<toolbarbutton id="sp-toolbar-inspect"
class="devtools-toolbarbutton"
label="&inspect.label;"
command="sp-cmd-inspect"/>
<toolbarbutton id="sp-toolbar-display"
class="devtools-toolbarbutton"
label="&display.label;"
command="sp-cmd-display"/>
<toolbarspacer/>
<toolbarbutton id="sp-toolbar-pprint"
class="devtools-toolbarbutton"
label="&pprint.label;"
command="sp-cmd-pprint"/>
</toolbar>
<popupset id="scratchpad-popups">
<menupopup id="scratchpad-text-popup">
<menuitem id="cMenu_cut"/>
<menuitem id="cMenu_copy"/>
<menuitem id="cMenu_paste"/>
<menuitem id="cMenu_delete"/>
<menuseparator/>
<menuitem id="cMenu_selectAll"/>
<menuseparator/>
<menuitem id="sp-text-run"
label="&run.label;"
accesskey="&run.accesskey;"
key="sp-key-run"
command="sp-cmd-run"/>
<menuitem id="sp-text-inspect"
label="&inspect.label;"
accesskey="&inspect.accesskey;"
key="sp-key-inspect"
command="sp-cmd-inspect"/>
<menuitem id="sp-text-display"
label="&display.label;"
accesskey="&display.accesskey;"
key="sp-key-display"
command="sp-cmd-display"/>
<menuitem id="sp-text-evalFunction"
label="&evalFunction.label;"
key="sp-key-evalFunction"
accesskey="&evalFunction.accesskey;"
command="sp-cmd-evalFunction"/>
<menuseparator/>
<menuitem id="sp-text-reloadAndRun"
label="&reloadAndRun.label;"
key="sp-key-reloadAndRun"
accesskey="&reloadAndRun.accesskey;"
command="sp-cmd-reloadAndRun"/>
</menupopup>
</popupset>
<notificationbox id="scratchpad-notificationbox" flex="1">
<hbox flex="1">
<vbox id="scratchpad-editor" flex="1"/>
<splitter class="devtools-side-splitter"/>
<tabbox id="scratchpad-sidebar" class="devtools-sidebar-tabs"
width="300"
hidden="true">
<tabs/>
<tabpanels flex="1"/>
</tabbox>
</hbox>
<toolbar id="statusbar-line-col" class="devtools-toolbar"/>
</notificationbox>
</window>

View file

@ -0,0 +1,6 @@
"use strict";
module.exports = {
// Extend from the shared list of defined globals for mochitests.
"extends": "../../../.eslintrc.mochitests.js"
};

View file

@ -0,0 +1,2 @@
Typ Datum Uhrzeit Quelle Kategorie Ereignis Benutzer Computer
Informationen 10.08.2012 16:07:11 MSDTC Datenträger 2444 Nicht zutreffend

View file

@ -0,0 +1,46 @@
[DEFAULT]
tags = devtools
subsuite = devtools
support-files = head.js
[browser_scratchpad_autocomplete.js]
[browser_scratchpad_browser_last_window_closing.js]
[browser_scratchpad_reset_undo.js]
[browser_scratchpad_display_outputs_errors.js]
[browser_scratchpad_eval_func.js]
[browser_scratchpad_goto_line_ui.js]
[browser_scratchpad_reload_and_run.js]
[browser_scratchpad_display_non_error_exceptions.js]
[browser_scratchpad_modeline.js]
[browser_scratchpad_chrome_context_pref.js]
[browser_scratchpad_help_key.js]
[browser_scratchpad_recent_files.js]
# [browser_scratchpad_confirm_close.js]
# Disable test due to bug 807234 becoming basically permanent
[browser_scratchpad_tab.js]
[browser_scratchpad_wrong_window_focus.js]
[browser_scratchpad_unsaved.js]
[browser_scratchpad_falsy.js]
[browser_scratchpad_edit_ui_updates.js]
[browser_scratchpad_revert_to_saved.js]
[browser_scratchpad_run_error_goto_line.js]
[browser_scratchpad_contexts.js]
[browser_scratchpad_execute_print.js]
[browser_scratchpad_files.js]
[browser_scratchpad_initialization.js]
[browser_scratchpad_inspect.js]
[browser_scratchpad_inspect_primitives.js]
[browser_scratchpad_long_string.js]
[browser_scratchpad_open.js]
support-files = NS_ERROR_ILLEGAL_INPUT.txt
[browser_scratchpad_open_error_console.js]
[browser_scratchpad_throw_output.js]
[browser_scratchpad_pprint-02.js]
[browser_scratchpad_pprint.js]
[browser_scratchpad_pprint_error_goto_line.js]
[browser_scratchpad_restore.js]
[browser_scratchpad_tab_switch.js]
[browser_scratchpad_ui.js]
[browser_scratchpad_close_toolbox.js]
[browser_scratchpad_remember_view_options.js]
[browser_scratchpad_disable_view_menu_items.js]

View file

@ -0,0 +1,66 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 968896 */
// Test the completions using numbers.
const source = "0x1.";
const completions = ["toExponential", "toFixed", "toString"];
const { Task } = require("devtools/shared/task");
function test() {
const options = { tabContent: "test scratchpad autocomplete" };
openTabAndScratchpad(options)
.then(Task.async(runTests))
.then(finish, console.error);
}
function* runTests([win, sp]) {
const {editor} = sp;
const editorWin = editor.container.contentWindow;
// Show the completions popup.
sp.setText(source);
sp.editor.setCursor({ line: 0, ch: source.length });
yield keyOnce("suggestion-entered", " ", { ctrlKey: true });
// Get the hints popup container.
const hints = editorWin.document.querySelector(".CodeMirror-hints");
ok(hints,
"The hint container should exist.");
is(hints.childNodes.length, 3,
"The hint container should have the completions.");
let i = 0;
for (let completion of completions) {
let active = hints.querySelector(".CodeMirror-hint-active");
is(active.textContent, completion,
"Check that completion " + i++ + " is what is expected.");
yield keyOnce("suggestion-entered", "VK_DOWN");
}
// We should have looped around to the first suggestion again. Accept it.
yield keyOnce("after-suggest", "VK_RETURN");
is(sp.getText(), source + completions[0],
"Autocompletion should work and select the right element.");
// Check that the information tooltips work.
sp.setText("5");
yield keyOnce("show-information", " ", { ctrlKey: true, shiftKey: true });
// Get the information container.
const info = editorWin.document.querySelector(".CodeMirror-Tern-information");
ok(info,
"Info tooltip should appear.");
is(info.textContent.slice(0, 6), "number",
"Info tooltip should have expected contents.");
function keyOnce(event, key, opts = {}) {
const p = editor.once(event);
EventUtils.synthesizeKey(key, opts, editorWin);
return p;
}
}

View file

@ -0,0 +1,79 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const BUTTON_POSITION_CANCEL = 1;
const BUTTON_POSITION_DONT_SAVE = 2;
function test()
{
waitForExplicitFinish();
// Observer must be attached *before* Scratchpad is opened.
CloseObserver.init();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onTabLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onTabLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html;charset=utf8,<p>test browser last window closing</p>";
}
function runTests({ Scratchpad })
{
let browser = Services.wm.getEnumerator("navigator:browser").getNext();
let oldPrompt = Services.prompt;
let button;
Services.prompt = {
confirmEx: () => button
};
Scratchpad.dirty = true;
// Test canceling close.
button = BUTTON_POSITION_CANCEL;
CloseObserver.expectedValue = true;
browser.BrowserTryToCloseWindow();
// Test accepting close.
button = BUTTON_POSITION_DONT_SAVE;
CloseObserver.expectedValue = false;
browser.BrowserTryToCloseWindow();
// Test closing without prompt needed.
Scratchpad.dirty = false;
browser.BrowserTryToCloseWindow();
Services.prompt = oldPrompt;
CloseObserver.uninit();
finish();
}
var CloseObserver = {
expectedValue: null,
init: function ()
{
Services.obs.addObserver(this, "browser-lastwindow-close-requested", false);
},
observe: function (aSubject)
{
aSubject.QueryInterface(Ci.nsISupportsPRBool);
let message = this.expectedValue ? "close" : "stay open";
ok(this.expectedValue === aSubject.data, "Expected browser to " + message);
aSubject.data = true;
},
uninit: function ()
{
Services.obs.removeObserver(this, "browser-lastwindow-close-requested", false);
},
};

View file

@ -0,0 +1,50 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 646070 */
var DEVTOOLS_CHROME_ENABLED = "devtools.chrome.enabled";
function test()
{
waitForExplicitFinish();
Services.prefs.setBoolPref(DEVTOOLS_CHROME_ENABLED, true);
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,Scratchpad test for bug 646070 - chrome context preference";
}
function runTests()
{
let sp = gScratchpadWindow.Scratchpad;
ok(sp, "Scratchpad object exists in new window");
let environmentMenu = gScratchpadWindow.document.
getElementById("sp-environment-menu");
ok(environmentMenu, "Environment menu element exists");
ok(!environmentMenu.hasAttribute("hidden"),
"Environment menu is visible");
let errorConsoleCommand = gScratchpadWindow.document.
getElementById("sp-cmd-errorConsole");
ok(errorConsoleCommand, "Error console command element exists");
ok(!errorConsoleCommand.hasAttribute("disabled"),
"Error console command is enabled");
let chromeContextCommand = gScratchpadWindow.document.
getElementById("sp-cmd-browserContext");
ok(chromeContextCommand, "Chrome context command element exists");
ok(!chromeContextCommand.hasAttribute("disabled"),
"Chrome context command is disabled");
Services.prefs.clearUserPref(DEVTOOLS_CHROME_ENABLED);
finish();
}

View file

@ -0,0 +1,38 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that closing the toolbox after having opened a scratchpad leaves the
// latter in a functioning state.
var {Task} = require("devtools/shared/task");
var {TargetFactory} = require("devtools/client/framework/target");
function test() {
const options = {
tabContent: "test closing toolbox and then reusing scratchpad"
};
openTabAndScratchpad(options)
.then(Task.async(runTests))
.then(finish, console.error);
}
function* runTests([win, sp]) {
// Use the scratchpad before opening the toolbox.
const source = "window.foobar = 7;";
sp.setText(source);
let [,, result] = yield sp.display();
is(result, 7, "Display produced the expected output.");
// Now open the toolbox and close it again.
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = yield gDevTools.showToolbox(target, "webconsole");
ok(toolbox, "Toolbox was opened.");
let closed = yield gDevTools.closeToolbox(target);
is(closed, true, "Toolbox was closed.");
// Now see if using the scratcphad works as expected.
sp.setText(source);
let [,, result2] = yield sp.display();
is(result2, 7,
"Display produced the expected output after the toolbox was gone.");
}

View file

@ -0,0 +1,230 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 653427 */
var tempScope = {};
Cu.import("resource://gre/modules/NetUtil.jsm", tempScope);
Cu.import("resource://gre/modules/FileUtils.jsm", tempScope);
var NetUtil = tempScope.NetUtil;
var FileUtils = tempScope.FileUtils;
// only finish() when correct number of tests are done
const expected = 9;
var count = 0;
function done()
{
if (++count == expected) {
cleanup();
finish();
}
}
var gFile;
var oldPrompt = Services.prompt;
var promptButton = -1;
function test()
{
waitForExplicitFinish();
gFile = createTempFile("fileForBug653427.tmp");
writeFile(gFile, "text", testUnsaved.call(this));
Services.prompt = {
confirmEx: function () {
return promptButton;
}
};
testNew();
testSavedFile();
gBrowser.selectedTab = gBrowser.addTab();
content.location = "data:text/html,<p>test scratchpad save file prompt on closing";
}
function testNew()
{
openScratchpad(function (win) {
win.Scratchpad.close(function () {
ok(win.closed, "new scratchpad window should close without prompting");
done();
});
}, {noFocus: true});
}
function testSavedFile()
{
openScratchpad(function (win) {
win.Scratchpad.filename = "test.js";
win.Scratchpad.editor.dirty = false;
win.Scratchpad.close(function () {
ok(win.closed, "scratchpad from file with no changes should close");
done();
});
}, {noFocus: true});
}
function testUnsaved()
{
function setFilename(aScratchpad, aFile) {
aScratchpad.setFilename(aFile);
}
testUnsavedFileCancel(setFilename);
testUnsavedFileSave(setFilename);
testUnsavedFileDontSave(setFilename);
testCancelAfterLoad();
function mockSaveFile(aScratchpad) {
let SaveFileStub = function (aCallback) {
/*
* An argument for aCallback must pass Components.isSuccessCode
*
* A version of isSuccessCode in JavaScript:
* function isSuccessCode(returnCode) {
* return (returnCode & 0x80000000) == 0;
* }
*/
aCallback(1);
};
aScratchpad.saveFile = SaveFileStub;
}
// Run these tests again but this time without setting a filename to
// test that Scratchpad always asks for confirmation on dirty editor.
testUnsavedFileCancel(mockSaveFile);
testUnsavedFileSave(mockSaveFile);
testUnsavedFileDontSave();
}
function testUnsavedFileCancel(aCallback = function () {})
{
openScratchpad(function (win) {
aCallback(win.Scratchpad, "test.js");
win.Scratchpad.editor.dirty = true;
promptButton = win.BUTTON_POSITION_CANCEL;
win.Scratchpad.close(function () {
ok(!win.closed, "cancelling dialog shouldn't close scratchpad");
win.close();
done();
});
}, {noFocus: true});
}
// Test a regression where our confirmation dialog wasn't appearing
// after openFile calls. See bug 801982.
function testCancelAfterLoad()
{
openScratchpad(function (win) {
win.Scratchpad.setRecentFile(gFile);
win.Scratchpad.openFile(0);
win.Scratchpad.editor.dirty = true;
promptButton = win.BUTTON_POSITION_CANCEL;
let EventStub = {
called: false,
preventDefault: function () {
EventStub.called = true;
}
};
win.Scratchpad.onClose(EventStub, function () {
ok(!win.closed, "cancelling dialog shouldn't close scratchpad");
ok(EventStub.called, "aEvent.preventDefault was called");
win.Scratchpad.editor.dirty = false;
win.close();
done();
});
}, {noFocus: true});
}
function testUnsavedFileSave(aCallback = function () {})
{
openScratchpad(function (win) {
win.Scratchpad.importFromFile(gFile, true, function (status, content) {
aCallback(win.Scratchpad, gFile.path);
let text = "new text";
win.Scratchpad.setText(text);
promptButton = win.BUTTON_POSITION_SAVE;
win.Scratchpad.close(function () {
ok(win.closed, 'pressing "Save" in dialog should close scratchpad');
readFile(gFile, function (savedContent) {
is(savedContent, text, 'prompted "Save" worked when closing scratchpad');
done();
});
});
});
}, {noFocus: true});
}
function testUnsavedFileDontSave(aCallback = function () {})
{
openScratchpad(function (win) {
aCallback(win.Scratchpad, gFile.path);
win.Scratchpad.editor.dirty = true;
promptButton = win.BUTTON_POSITION_DONT_SAVE;
win.Scratchpad.close(function () {
ok(win.closed, 'pressing "Don\'t Save" in dialog should close scratchpad');
done();
});
}, {noFocus: true});
}
function cleanup()
{
Services.prompt = oldPrompt;
gFile.remove(false);
gFile = null;
}
function createTempFile(name)
{
let file = FileUtils.getFile("TmpD", [name]);
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
file.QueryInterface(Ci.nsILocalFile);
return file;
}
function writeFile(file, content, callback)
{
let fout = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
fout.init(file.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
0o644, fout.DEFER_OPEN);
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
let fileContentStream = converter.convertToInputStream(content);
NetUtil.asyncCopy(fileContentStream, fout, callback);
}
function readFile(file, callback)
{
let channel = NetUtil.newChannel({
uri: NetUtil.newURI(file),
loadUsingSystemPrincipal: true});
channel.contentType = "application/javascript";
NetUtil.asyncFetch(channel, function (inputStream, status) {
ok(Components.isSuccessCode(status),
"file was read successfully");
let content = NetUtil.readInputStreamToString(inputStream,
inputStream.available());
callback(content);
});
}

View file

@ -0,0 +1,149 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,test context switch in Scratchpad";
}
function runTests() {
let sp = gScratchpadWindow.Scratchpad;
let contentMenu = gScratchpadWindow.document.getElementById("sp-menu-content");
let chromeMenu = gScratchpadWindow.document.getElementById("sp-menu-browser");
let notificationBox = sp.notificationBox;
ok(contentMenu, "found #sp-menu-content");
ok(chromeMenu, "found #sp-menu-browser");
ok(notificationBox, "found Scratchpad.notificationBox");
let tests = [{
method: "run",
prepare: function* () {
sp.setContentContext();
is(sp.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_CONTENT,
"executionContext is content");
is(contentMenu.getAttribute("checked"), "true",
"content menuitem is checked");
isnot(chromeMenu.getAttribute("checked"), "true",
"chrome menuitem is not checked");
ok(!notificationBox.currentNotification,
"there is no notification in content context");
sp.editor.setText("window.foobarBug636725 = 'aloha';");
let pageResult = yield inContent(function* () {
return content.wrappedJSObject.foobarBug636725;
});
ok(!pageResult, "no content.foobarBug636725");
},
then: function* () {
is(content.wrappedJSObject.foobarBug636725, "aloha",
"content.foobarBug636725 has been set");
}
}, {
method: "run",
prepare: function* () {
sp.setBrowserContext();
is(sp.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_BROWSER,
"executionContext is chrome");
is(chromeMenu.getAttribute("checked"), "true",
"chrome menuitem is checked");
isnot(contentMenu.getAttribute("checked"), "true",
"content menuitem is not checked");
ok(notificationBox.currentNotification,
"there is a notification in browser context");
let [ from, to ] = sp.editor.getPosition(31, 32);
sp.editor.replaceText("2'", from, to);
is(sp.getText(), "window.foobarBug636725 = 'aloha2';",
"setText() worked");
},
then: function* () {
is(window.foobarBug636725, "aloha2",
"window.foobarBug636725 has been set");
delete window.foobarBug636725;
ok(!window.foobarBug636725, "no window.foobarBug636725");
}
}, {
method: "run",
prepare: function* () {
sp.editor.replaceText("gBrowser", sp.editor.getPosition(7));
is(sp.getText(), "window.gBrowser",
"setText() worked with no end for the replace range");
},
then: function* ([, , result]) {
is(result.class, "XULElement",
"chrome context has access to chrome objects");
}
}, {
method: "run",
prepare: function* () {
// Check that the sandbox is cached.
sp.editor.setText("typeof foobarBug636725cache;");
},
then: function* ([, , result]) {
is(result, "undefined", "global variable does not exist");
}
}, {
method: "run",
prepare: function* () {
sp.editor.setText("window.foobarBug636725cache = 'foo';" +
"typeof foobarBug636725cache;");
},
then: function* ([, , result]) {
is(result, "string",
"global variable exists across two different executions");
}
}, {
method: "run",
prepare: function* () {
sp.editor.setText("window.foobarBug636725cache2 = 'foo';" +
"typeof foobarBug636725cache2;");
},
then: function* ([, , result]) {
is(result, "string",
"global variable exists across two different executions");
}
}, {
method: "run",
prepare: function* () {
sp.setContentContext();
is(sp.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_CONTENT,
"executionContext is content");
sp.editor.setText("typeof foobarBug636725cache2;");
},
then: function* ([, , result]) {
is(result, "undefined",
"global variable no longer exists after changing the context");
}
}];
runAsyncCallbackTests(sp, tests).then(() => {
sp.setBrowserContext();
sp.editor.setText("delete foobarBug636725cache;" +
"delete foobarBug636725cache2;");
sp.run().then(finish);
});
}

View file

@ -0,0 +1,66 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test if the view menu items "Larger Font" and "Smaller Font" are disabled
// when the font size reaches the maximum/minimum values.
var {Task} = require("devtools/shared/task");
function test() {
const options = {
tabContent: 'test if view menu items "Larger Font" and "Smaller Font" are enabled/disabled.'
};
openTabAndScratchpad(options)
.then(Task.async(runTests))
.then(finish, console.error);
}
function* runTests([win, sp]) {
yield testMaximumFontSize(win, sp);
yield testMinimumFontSize(win, sp);
}
const MAXIMUM_FONT_SIZE = 96;
const MINIMUM_FONT_SIZE = 6;
const NORMAL_FONT_SIZE = 12;
var testMaximumFontSize = Task.async(function* (win, sp) {
let doc = win.document;
Services.prefs.clearUserPref("devtools.scratchpad.editorFontSize");
let menu = doc.getElementById("sp-menu-larger-font");
for (let i = NORMAL_FONT_SIZE; i <= MAXIMUM_FONT_SIZE; i++) {
menu.doCommand();
}
let cmd = doc.getElementById("sp-cmd-larger-font");
ok(cmd.getAttribute("disabled") === "true", 'Command "sp-cmd-larger-font" is disabled.');
menu = doc.getElementById("sp-menu-smaller-font");
menu.doCommand();
ok(cmd.hasAttribute("disabled") === false, 'Command "sp-cmd-larger-font" is enabled.');
});
var testMinimumFontSize = Task.async(function* (win, sp) {
let doc = win.document;
let menu = doc.getElementById("sp-menu-smaller-font");
for (let i = MAXIMUM_FONT_SIZE; i >= MINIMUM_FONT_SIZE; i--) {
menu.doCommand();
}
let cmd = doc.getElementById("sp-cmd-smaller-font");
ok(cmd.getAttribute("disabled") === "true", 'Command "sp-cmd-smaller-font" is disabled.');
menu = doc.getElementById("sp-menu-larger-font");
menu.doCommand();
ok(cmd.hasAttribute("disabled") === false, 'Command "sp-cmd-smaller-font" is enabled.');
Services.prefs.clearUserPref("devtools.scratchpad.editorFontSize");
});

View file

@ -0,0 +1,110 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 756681 */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function browserLoad() {
gBrowser.selectedBrowser.removeEventListener("load", browserLoad, true);
openScratchpad(runTests, {"state":{"text":""}});
}, true);
content.location = "data:text/html, test that exceptions are output as " +
"comments correctly in Scratchpad";
}
function runTests()
{
var scratchpad = gScratchpadWindow.Scratchpad;
var message = "\"Hello World!\"";
var openComment = "\n/*\n";
var closeComment = "\n*/";
var error1 = "throw new Error(\"Ouch!\")";
var error2 = "throw \"A thrown string\"";
var error3 = "throw {}";
var error4 = "document.body.appendChild(document.body)";
let tests = [{
// Display message
method: "display",
code: message,
result: message + openComment + "Hello World!" + closeComment,
label: "message display output"
},
{
// Display error1, throw new Error("Ouch")
method: "display",
code: error1,
result: error1 + openComment +
"Exception: Error: Ouch!\n@" + scratchpad.uniqueName + ":1:7" + closeComment,
label: "error display output"
},
{
// Display error2, throw "A thrown string"
method: "display",
code: error2,
result: error2 + openComment + "Exception: A thrown string" + closeComment,
label: "thrown string display output"
},
{
// Display error3, throw {}
method: "display",
code: error3,
result: error3 + openComment + "Exception: [object Object]" + closeComment,
label: "thrown object display output"
},
{
// Display error4, document.body.appendChild(document.body)
method: "display",
code: error4,
result: error4 + openComment + "Exception: HierarchyRequestError: Node cannot be inserted " +
"at the specified point in the hierarchy\n@" +
scratchpad.uniqueName + ":1:0" + closeComment,
label: "Alternative format error display output"
},
{
// Run message
method: "run",
code: message,
result: message,
label: "message run output"
},
{
// Run error1, throw new Error("Ouch")
method: "run",
code: error1,
result: error1 + openComment +
"Exception: Error: Ouch!\n@" + scratchpad.uniqueName + ":1:7" + closeComment,
label: "error run output"
},
{
// Run error2, throw "A thrown string"
method: "run",
code: error2,
result: error2 + openComment + "Exception: A thrown string" + closeComment,
label: "thrown string run output"
},
{
// Run error3, throw {}
method: "run",
code: error3,
result: error3 + openComment + "Exception: [object Object]" + closeComment,
label: "thrown object run output"
},
{
// Run error4, document.body.appendChild(document.body)
method: "run",
code: error4,
result: error4 + openComment + "Exception: HierarchyRequestError: Node cannot be inserted " +
"at the specified point in the hierarchy\n@" +
scratchpad.uniqueName + ":1:0" + closeComment,
label: "Alternative format error run output"
}];
runAsyncTests(scratchpad, tests).then(finish);
}

View file

@ -0,0 +1,72 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 690552 */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function browserLoad() {
gBrowser.selectedBrowser.removeEventListener("load", browserLoad, true);
openScratchpad(runTests, {"state":{"text":""}});
}, true);
content.location = "data:text/html,<p>test that exceptions are output as " +
"comments for 'display' and not sent to the console in Scratchpad";
}
function runTests()
{
let scratchpad = gScratchpadWindow.Scratchpad;
let message = "\"Hello World!\"";
let openComment = "\n/*\n";
let closeComment = "\n*/";
let error = "throw new Error(\"Ouch!\")";
let syntaxError = "(";
let tests = [{
method: "display",
code: message,
result: message + openComment + "Hello World!" + closeComment,
label: "message display output"
},
{
method: "display",
code: error,
result: error + openComment + "Exception: Error: Ouch!\n@" +
scratchpad.uniqueName + ":1:7" + closeComment,
label: "error display output",
},
{
method: "display",
code: syntaxError,
result: syntaxError + openComment + "Exception: SyntaxError: expected expression, got end of script\n@" +
scratchpad.uniqueName + ":1" + closeComment,
label: "syntaxError display output",
},
{
method: "run",
code: message,
result: message,
label: "message run output",
},
{
method: "run",
code: error,
result: error + openComment + "Exception: Error: Ouch!\n@" +
scratchpad.uniqueName + ":1:7" + closeComment,
label: "error run output",
},
{
method: "run",
code: syntaxError,
result: syntaxError + openComment + "Exception: SyntaxError: expected expression, got end of script\n@" +
scratchpad.uniqueName + ":1" + closeComment,
label: "syntaxError run output",
}];
runAsyncTests(scratchpad, tests).then(finish);
}

View file

@ -0,0 +1,206 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 699130 */
"use strict";
var WebConsoleUtils = require("devtools/client/webconsole/utils").Utils;
var DEVTOOLS_CHROME_ENABLED = "devtools.chrome.enabled";
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
Services.prefs.setBoolPref(DEVTOOLS_CHROME_ENABLED, false);
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,test Edit menu updates Scratchpad - bug 699130";
}
function runTests()
{
let sp = gScratchpadWindow.Scratchpad;
let doc = gScratchpadWindow.document;
let winUtils = gScratchpadWindow.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
let OS = Services.appinfo.OS;
info("will test the Edit menu");
let pass = 0;
sp.setText("bug 699130: hello world! (edit menu)");
let editMenu = doc.getElementById("sp-edit-menu");
ok(editMenu, "the Edit menu");
let menubar = editMenu.parentNode;
ok(menubar, "menubar found");
let editMenuIndex = -1;
for (let i = 0; i < menubar.children.length; i++) {
if (menubar.children[i] === editMenu) {
editMenuIndex = i;
break;
}
}
isnot(editMenuIndex, -1, "Edit menu index is correct");
let menuPopup = editMenu.menupopup;
ok(menuPopup, "the Edit menupopup");
let cutItem = doc.getElementById("menu_cut");
ok(cutItem, "the Cut menuitem");
let pasteItem = doc.getElementById("menu_paste");
ok(pasteItem, "the Paste menuitem");
let anchor = doc.documentElement;
let isContextMenu = false;
let oldVal = sp.editor.getText();
let testSelfXss = function (oldVal) {
// Self xss prevention tests (bug 994134)
info("Self xss paste tests");
is(WebConsoleUtils.usageCount, 0, "Test for usage count getter");
let notificationbox = doc.getElementById("scratchpad-notificationbox");
let notification = notificationbox.getNotificationWithValue("selfxss-notification");
ok(notification, "Self-xss notification shown");
is(oldVal, sp.editor.getText(), "Paste blocked by self-xss prevention");
Services.prefs.setIntPref("devtools.selfxss.count", 10);
notificationbox.removeAllNotifications(true);
openMenu(10, 10, firstShow);
};
let openMenu = function (aX, aY, aCallback) {
if (!editMenu || OS != "Darwin") {
menuPopup.addEventListener("popupshown", function onPopupShown() {
menuPopup.removeEventListener("popupshown", onPopupShown, false);
executeSoon(aCallback);
}, false);
}
executeSoon(function () {
if (editMenu) {
if (OS == "Darwin") {
winUtils.forceUpdateNativeMenuAt(editMenuIndex);
executeSoon(aCallback);
} else {
editMenu.open = true;
}
} else {
menuPopup.openPopup(anchor, "overlap", aX, aY, isContextMenu, false);
}
});
};
let closeMenu = function (aCallback) {
if (!editMenu || OS != "Darwin") {
menuPopup.addEventListener("popuphidden", function onPopupHidden() {
menuPopup.removeEventListener("popuphidden", onPopupHidden, false);
executeSoon(aCallback);
}, false);
}
executeSoon(function () {
if (editMenu) {
if (OS == "Darwin") {
winUtils.forceUpdateNativeMenuAt(editMenuIndex);
executeSoon(aCallback);
} else {
editMenu.open = false;
}
} else {
menuPopup.hidePopup();
}
});
};
let firstShow = function () {
ok(!cutItem.hasAttribute("disabled"), "cut menuitem is enabled");
closeMenu(firstHide);
};
let firstHide = function () {
sp.editor.setSelection({ line: 0, ch: 0 }, { line: 0, ch: 10 });
openMenu(11, 11, showAfterSelect);
};
let showAfterSelect = function () {
ok(!cutItem.hasAttribute("disabled"), "cut menuitem is enabled after select");
closeMenu(hideAfterSelect);
};
let hideAfterSelect = function () {
sp.editor.on("change", onCut);
waitForFocus(function () {
let selectedText = sp.editor.getSelection();
ok(selectedText.length > 0, "non-empty selected text will be cut");
EventUtils.synthesizeKey("x", {accelKey: true}, gScratchpadWindow);
}, gScratchpadWindow);
};
let onCut = function () {
sp.editor.off("change", onCut);
openMenu(12, 12, showAfterCut);
};
let showAfterCut = function () {
ok(!cutItem.hasAttribute("disabled"), "cut menuitem is enabled after cut");
ok(!pasteItem.hasAttribute("disabled"), "paste menuitem is enabled after cut");
closeMenu(hideAfterCut);
};
let hideAfterCut = function () {
waitForFocus(function () {
sp.editor.on("change", onPaste);
EventUtils.synthesizeKey("v", {accelKey: true}, gScratchpadWindow);
}, gScratchpadWindow);
};
let onPaste = function () {
sp.editor.off("change", onPaste);
openMenu(13, 13, showAfterPaste);
};
let showAfterPaste = function () {
ok(!cutItem.hasAttribute("disabled"), "cut menuitem is enabled after paste");
ok(!pasteItem.hasAttribute("disabled"), "paste menuitem is enabled after paste");
closeMenu(hideAfterPaste);
};
let hideAfterPaste = function () {
if (pass == 0) {
pass++;
testContextMenu();
} else {
Services.prefs.clearUserPref(DEVTOOLS_CHROME_ENABLED);
finish();
}
};
let testContextMenu = function () {
info("will test the context menu");
editMenu = null;
isContextMenu = true;
menuPopup = doc.getElementById("scratchpad-text-popup");
ok(menuPopup, "the context menupopup");
cutItem = doc.getElementById("cMenu_cut");
ok(cutItem, "the Cut menuitem");
pasteItem = doc.getElementById("cMenu_paste");
ok(pasteItem, "the Paste menuitem");
sp.setText("bug 699130: hello world! (context menu)");
openMenu(10, 10, firstShow);
};
waitForFocus(function () {
WebConsoleUtils.usageCount = 0;
EventUtils.synthesizeKey("v", {accelKey: true}, gScratchpadWindow);
testSelfXss(oldVal);
}, gScratchpadWindow);
}

View file

@ -0,0 +1,86 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html;charset=utf8,test Scratchpad eval function.";
}
function reportErrorAndQuit(error) {
DevToolsUtils.reportException("browser_scratchpad_eval_func.js", error);
ok(false);
finish();
}
function runTests(sw)
{
const sp = sw.Scratchpad;
let foo = "" + function main() { console.log(1); };
let bar = "var bar = " + (() => { console.log(2); });
const fullText =
foo + "\n" +
"\n" +
bar + "\n";
sp.setText(fullText);
// On the function declaration.
sp.editor.setCursor({ line: 0, ch: 18 });
sp.evalTopLevelFunction()
.then(([text, error, result]) => {
is(text, foo, "Should re-eval foo.");
ok(!error, "Should not have got an error.");
ok(result, "Should have got a result.");
})
// On the arrow function.
.then(() => {
sp.editor.setCursor({ line: 2, ch: 18 });
return sp.evalTopLevelFunction();
})
.then(([text, error, result]) => {
is(text, bar.replace("var ", ""), "Should re-eval bar.");
ok(!error, "Should not have got an error.");
ok(result, "Should have got a result.");
})
// On the empty line.
.then(() => {
sp.editor.setCursor({ line: 1, ch: 0 });
return sp.evalTopLevelFunction();
})
.then(([text, error, result]) => {
is(text, fullText,
"Should get full text back since we didn't find a specific function.");
ok(!error, "Should not have got an error.");
ok(!result, "Should not have got a result.");
})
// Syntax error.
.then(() => {
sp.setText("function {}");
sp.editor.setCursor({ line: 0, ch: 9 });
return sp.evalTopLevelFunction();
})
.then(([text, error, result]) => {
is(text, "function {}",
"Should get the full text back since there was a parse error.");
ok(!error, "Should not have got an error");
ok(!result, "Should not have got a result");
ok(sp.getText().includes("SyntaxError"),
"We should have written the syntax error to the scratchpad.");
})
.then(finish, reportErrorAndQuit);
}

View file

@ -0,0 +1,116 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onTabLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onTabLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,<p>test run() and display() in Scratchpad";
}
function runTests() {
let sp = gScratchpadWindow.Scratchpad;
let tests = [{
method: "run",
prepare: function* () {
yield inContent(function* () {
content.wrappedJSObject.foobarBug636725 = 1;
});
sp.editor.setText("++window.foobarBug636725");
},
then: function* ([code, , result]) {
is(code, sp.getText(), "code is correct");
let pageResult = yield inContent(function* () {
return content.wrappedJSObject.foobarBug636725;
});
is(result, pageResult,
"result is correct");
is(sp.getText(), "++window.foobarBug636725",
"run() does not change the editor content");
is(pageResult, 2, "run() updated window.foobarBug636725");
}
}, {
method: "display",
prepare: function* () {},
then: function* () {
let pageResult = yield inContent(function* () {
return content.wrappedJSObject.foobarBug636725;
});
is(pageResult, 3, "display() updated window.foobarBug636725");
is(sp.getText(), "++window.foobarBug636725\n/*\n3\n*/",
"display() shows evaluation result in the textbox");
is(sp.editor.getSelection(), "\n/*\n3\n*/", "getSelection is correct");
}
}, {
method: "run",
prepare: function* () {
sp.editor.setText("window.foobarBug636725 = 'a';\n" +
"window.foobarBug636725 = 'b';");
sp.editor.setSelection({ line: 0, ch: 0 }, { line: 0, ch: 29 });
},
then: function* ([code, , result]) {
is(code, "window.foobarBug636725 = 'a';", "code is correct");
is(result, "a", "result is correct");
is(sp.getText(), "window.foobarBug636725 = 'a';\n" +
"window.foobarBug636725 = 'b';",
"run() does not change the textbox value");
let pageResult = yield inContent(function* () {
return content.wrappedJSObject.foobarBug636725;
});
is(pageResult, "a", "run() worked for the selected range");
}
}, {
method: "display",
prepare: function* () {
sp.editor.setText("window.foobarBug636725 = 'c';\n" +
"window.foobarBug636725 = 'b';");
sp.editor.setSelection({ line: 0, ch: 0 }, { line: 0, ch: 22 });
},
then: function* () {
let pageResult = yield inContent(function* () {
return content.wrappedJSObject.foobarBug636725;
});
is(pageResult, "a", "display() worked for the selected range");
is(sp.getText(), "window.foobarBug636725" +
"\n/*\na\n*/" +
" = 'c';\n" +
"window.foobarBug636725 = 'b';",
"display() shows evaluation result in the textbox");
is(sp.editor.getSelection(), "\n/*\na\n*/", "getSelection is correct");
}
}];
runAsyncCallbackTests(sp, tests).then(function () {
ok(sp.editor.somethingSelected(), "something is selected");
sp.editor.dropSelection();
ok(!sp.editor.somethingSelected(), "something is no longer selected");
ok(!sp.editor.getSelection(), "getSelection is empty");
// Test undo/redo.
sp.editor.setText("foo1");
sp.editor.setText("foo2");
is(sp.getText(), "foo2", "editor content updated");
sp.undo();
is(sp.getText(), "foo1", "undo() works");
sp.redo();
is(sp.getText(), "foo2", "redo() works");
finish();
});
}

View file

@ -0,0 +1,69 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 679467 */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(testFalsy);
}, true);
content.location = "data:text/html,<p>test falsy display() values in Scratchpad";
}
function testFalsy()
{
let scratchpad = gScratchpadWindow.Scratchpad;
verifyFalsies(scratchpad).then(function () {
scratchpad.setBrowserContext();
verifyFalsies(scratchpad).then(finish);
});
}
function verifyFalsies(scratchpad)
{
let tests = [{
method: "display",
code: "undefined",
result: "undefined\n/*\nundefined\n*/",
label: "undefined is displayed"
},
{
method: "display",
code: "false",
result: "false\n/*\nfalse\n*/",
label: "false is displayed"
},
{
method: "display",
code: "0",
result: "0\n/*\n0\n*/",
label: "0 is displayed"
},
{
method: "display",
code: "null",
result: "null\n/*\nnull\n*/",
label: "null is displayed"
},
{
method: "display",
code: "NaN",
result: "NaN\n/*\nNaN\n*/",
label: "NaN is displayed"
},
{
method: "display",
code: "''",
result: "''\n/*\n\n*/",
label: "the empty string is displayed"
}];
return runAsyncTests(scratchpad, tests);
}

View file

@ -0,0 +1,119 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Reference to the Scratchpad object.
var gScratchpad;
// Reference to the temporary nsIFile we will work with.
var gFile;
// The temporary file content.
var gFileContent = "hello.world('bug636725');";
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,<p>test file open and save in Scratchpad";
}
function runTests()
{
gScratchpad = gScratchpadWindow.Scratchpad;
createTempFile("fileForBug636725.tmp", gFileContent, function (aStatus, aFile) {
ok(Components.isSuccessCode(aStatus),
"The temporary file was saved successfully");
gFile = aFile;
gScratchpad.importFromFile(gFile.QueryInterface(Ci.nsILocalFile), true,
fileImported);
});
}
function fileImported(aStatus, aFileContent)
{
ok(Components.isSuccessCode(aStatus),
"the temporary file was imported successfully with Scratchpad");
is(aFileContent, gFileContent,
"received data is correct");
is(gScratchpad.getText(), gFileContent,
"the editor content is correct");
is(gScratchpad.dirty, false,
"the editor marks imported file as saved");
// Save the file after changes.
gFileContent += "// omg, saved!";
gScratchpad.editor.setText(gFileContent);
gScratchpad.exportToFile(gFile.QueryInterface(Ci.nsILocalFile), true, true,
fileExported);
}
function fileExported(aStatus)
{
ok(Components.isSuccessCode(aStatus),
"the temporary file was exported successfully with Scratchpad");
let oldContent = gFileContent;
// Attempt another file save, with confirmation which returns false.
gFileContent += "// omg, saved twice!";
gScratchpad.editor.setText(gFileContent);
let oldConfirm = gScratchpadWindow.confirm;
let askedConfirmation = false;
gScratchpadWindow.confirm = function () {
askedConfirmation = true;
return false;
};
gScratchpad.exportToFile(gFile.QueryInterface(Ci.nsILocalFile), false, true,
fileExported2);
gScratchpadWindow.confirm = oldConfirm;
ok(askedConfirmation, "exportToFile() asked for overwrite confirmation");
gFileContent = oldContent;
let channel = NetUtil.newChannel({
uri: NetUtil.newURI(gFile),
loadUsingSystemPrincipal: true});
channel.contentType = "application/javascript";
// Read back the temporary file.
NetUtil.asyncFetch(channel, fileRead);
}
function fileExported2()
{
ok(false, "exportToFile() did not cancel file overwrite");
}
function fileRead(aInputStream, aStatus)
{
ok(Components.isSuccessCode(aStatus),
"the temporary file was read back successfully");
let updatedContent =
NetUtil.readInputStreamToString(aInputStream, aInputStream.available());
is(updatedContent, gFileContent, "file properly updated");
// Done!
gFile.remove(false);
gFile = null;
gScratchpad = null;
finish();
}

View file

@ -0,0 +1,43 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 714942 */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function browserLoad() {
gBrowser.selectedBrowser.removeEventListener("load", browserLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,<p>test the 'Jump to line' feature in Scratchpad";
}
function runTests(aWindow, aScratchpad)
{
let editor = aScratchpad.editor;
let text = "foobar bug650345\nBug650345 bazbaz\nfoobar omg\ntest";
editor.setText(text);
editor.setCursor({ line: 0, ch: 0 });
let oldPrompt = editor.openDialog;
let desiredValue;
editor.openDialog = function (text, cb) {
cb(desiredValue);
};
desiredValue = 3;
EventUtils.synthesizeKey("J", {accelKey: true}, aWindow);
is(editor.getCursor().line, 2, "line is correct");
desiredValue = 2;
EventUtils.synthesizeKey("J", {accelKey: true}, aWindow);
is(editor.getCursor().line, 1, "line is correct (again)");
editor.openDialog = oldPrompt;
finish();
}

View file

@ -0,0 +1,59 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 650760 */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
content.location = "data:text/html,Test keybindings for opening Scratchpad MDN Documentation, bug 650760";
gBrowser.selectedBrowser.addEventListener("load", function onTabLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onTabLoad, true);
openScratchpad(runTest);
}, true);
}
function runTest()
{
let sp = gScratchpadWindow.Scratchpad;
ok(sp, "Scratchpad object exists in new window");
ok(sp.editor.hasFocus(), "the editor has focus");
let keyid = gScratchpadWindow.document.getElementById("key_openHelp");
let modifiers = keyid.getAttribute("modifiers");
let key = null;
if (keyid.getAttribute("keycode"))
key = keyid.getAttribute("keycode");
else if (keyid.getAttribute("key"))
key = keyid.getAttribute("key");
isnot(key, null, "Successfully retrieved keycode/key");
var aEvent = {
shiftKey: modifiers.match("shift"),
ctrlKey: modifiers.match("ctrl"),
altKey: modifiers.match("alt"),
metaKey: modifiers.match("meta"),
accelKey: modifiers.match("accel")
};
info("check that the MDN page is opened on \"F1\"");
let linkClicked = false;
sp.openDocumentationPage = function (event) { linkClicked = true; };
EventUtils.synthesizeKey(key, aEvent, gScratchpadWindow);
is(linkClicked, true, "MDN page will open");
finishTest();
}
function finishTest()
{
gScratchpadWindow.close();
finish();
}

View file

@ -0,0 +1,50 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
var DEVTOOLS_CHROME_ENABLED = "devtools.chrome.enabled";
function test()
{
waitForExplicitFinish();
Services.prefs.setBoolPref(DEVTOOLS_CHROME_ENABLED, false);
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,initialization test for Scratchpad";
}
function runTests()
{
let sp = gScratchpadWindow.Scratchpad;
ok(sp, "Scratchpad object exists in new window");
is(typeof sp.run, "function", "Scratchpad.run() exists");
is(typeof sp.inspect, "function", "Scratchpad.inspect() exists");
is(typeof sp.display, "function", "Scratchpad.display() exists");
let environmentMenu = gScratchpadWindow.document.
getElementById("sp-environment-menu");
ok(environmentMenu, "Environment menu element exists");
ok(environmentMenu.hasAttribute("hidden"),
"Environment menu is not visible");
let errorConsoleCommand = gScratchpadWindow.document.
getElementById("sp-cmd-errorConsole");
ok(errorConsoleCommand, "Error console command element exists");
is(errorConsoleCommand.getAttribute("disabled"), "true",
"Error console command is disabled");
let chromeContextCommand = gScratchpadWindow.document.
getElementById("sp-cmd-browserContext");
ok(chromeContextCommand, "Chrome context command element exists");
is(chromeContextCommand.getAttribute("disabled"), "true",
"Chrome context command is disabled");
Services.prefs.clearUserPref(DEVTOOLS_CHROME_ENABLED);
finish();
}

View file

@ -0,0 +1,55 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html;charset=utf8,<p>test inspect() in Scratchpad</p>";
}
function runTests()
{
let sp = gScratchpadWindow.Scratchpad;
sp.setText("({ a: 'foobarBug636725' })");
sp.inspect().then(function () {
let sidebar = sp.sidebar;
ok(sidebar.visible, "sidebar is open");
let found = false;
outer: for (let scope of sidebar.variablesView) {
for (let [, obj] of scope) {
for (let [, prop] of obj) {
if (prop.name == "a" && prop.value == "foobarBug636725") {
found = true;
break outer;
}
}
}
}
ok(found, "found the property");
let tabbox = sidebar._sidebar._tabbox;
is(tabbox.width, 300, "Scratchpad sidebar width is correct");
ok(!tabbox.hasAttribute("hidden"), "Scratchpad sidebar visible");
sidebar.hide();
ok(tabbox.hasAttribute("hidden"), "Scratchpad sidebar hidden");
sp.inspect().then(function () {
is(tabbox.width, 300, "Scratchpad sidebar width is still correct");
ok(!tabbox.hasAttribute("hidden"), "Scratchpad sidebar visible again");
finish();
});
});
}

View file

@ -0,0 +1,61 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that inspecting primitive values uses the object inspector, not an
// inline comment.
var {Task} = require("devtools/shared/task");
function test() {
const options = {
tabContent: "test inspecting primitive values"
};
openTabAndScratchpad(options)
.then(Task.async(runTests))
.then(finish, console.error);
}
function* runTests([win, sp]) {
// Inspect a number.
yield checkResults(sp, 7);
// Inspect a string.
yield checkResults(sp, "foobar", true);
// Inspect a boolean.
yield checkResults(sp, true);
}
// Helper function that does the actual testing.
var checkResults = Task.async(function* (sp, value, isString = false) {
let sourceValue = value;
if (isString) {
sourceValue = '"' + value + '"';
}
let source = "var foobar = " + sourceValue + "; foobar";
sp.setText(source);
yield sp.inspect();
let sidebar = sp.sidebar;
ok(sidebar.visible, "sidebar is open");
let found = false;
outer: for (let scope of sidebar.variablesView) {
for (let [, obj] of scope) {
for (let [, prop] of obj) {
if (prop.name == "value" && prop.value == value) {
found = true;
break outer;
}
}
}
}
ok(found, "found the value of " + value);
let tabbox = sidebar._sidebar._tabbox;
ok(!tabbox.hasAttribute("hidden"), "Scratchpad sidebar visible");
sidebar.hide();
ok(tabbox.hasAttribute("hidden"), "Scratchpad sidebar hidden");
});

View file

@ -0,0 +1,30 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html;charset=utf8,<p>test long string in Scratchpad</p>";
}
function runTests()
{
let sp = gScratchpadWindow.Scratchpad;
sp.setText("'0'.repeat(10000)");
sp.display().then(() => {
is(sp.getText(), "'0'.repeat(10000)\n" +
"/*\n" + "0".repeat(10000) + "\n*/",
"display()ing a long string works");
finish();
});
}

View file

@ -0,0 +1,87 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 644413 */
var gScratchpad; // Reference to the Scratchpad object.
var gFile; // Reference to the temporary nsIFile we will work with.
var DEVTOOLS_CHROME_ENABLED = "devtools.chrome.enabled";
// The temporary file content.
var gFileContent = "function main() { return 0; }";
function test() {
waitForExplicitFinish();
Services.prefs.setBoolPref(DEVTOOLS_CHROME_ENABLED, false);
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,<p>test file open and save in Scratchpad";
}
function runTests() {
gScratchpad = gScratchpadWindow.Scratchpad;
function size(obj) { return Object.keys(obj).length; }
// Test Scratchpad._scanModeLine method.
let obj = gScratchpad._scanModeLine();
is(size(obj), 0, "Mode-line object has no properties");
obj = gScratchpad._scanModeLine("/* This is not a mode-line comment */");
is(size(obj), 0, "Mode-line object has no properties");
obj = gScratchpad._scanModeLine("/* -sp-context:browser */");
is(size(obj), 1, "Mode-line object has one property");
is(obj["-sp-context"], "browser");
obj = gScratchpad._scanModeLine("/* -sp-context: browser */");
is(size(obj), 1, "Mode-line object has one property");
is(obj["-sp-context"], "browser");
obj = gScratchpad._scanModeLine("// -sp-context: browser");
is(size(obj), 1, "Mode-line object has one property");
is(obj["-sp-context"], "browser");
obj = gScratchpad._scanModeLine("/* -sp-context:browser, other:true */");
is(size(obj), 2, "Mode-line object has two properties");
is(obj["-sp-context"], "browser");
is(obj["other"], "true");
// Test importing files with a mode-line in them.
let content = "/* -sp-context:browser */\n" + gFileContent;
createTempFile("fileForBug644413.tmp", content, function (aStatus, aFile) {
ok(Components.isSuccessCode(aStatus), "File was saved successfully");
gFile = aFile;
gScratchpad.importFromFile(gFile.QueryInterface(Ci.nsILocalFile), true, fileImported);
});
}
function fileImported(status, content) {
ok(Components.isSuccessCode(status), "File was imported successfully");
// Since devtools.chrome.enabled is off, Scratchpad should still be in
// the content context.
is(gScratchpad.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_CONTENT);
// Set the pref and try again.
Services.prefs.setBoolPref(DEVTOOLS_CHROME_ENABLED, true);
gScratchpad.importFromFile(gFile.QueryInterface(Ci.nsILocalFile), true, function (status, content) {
ok(Components.isSuccessCode(status), "File was imported successfully");
is(gScratchpad.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_BROWSER);
gFile.remove(false);
gFile = null;
gScratchpad = null;
finish();
});
}
registerCleanupFunction(function () {
Services.prefs.clearUserPref(DEVTOOLS_CHROME_ENABLED);
});

View file

@ -0,0 +1,101 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// only finish() when correct number of tests are done
const expected = 4;
var count = 0;
var lastUniqueName = null;
function done()
{
if (++count == expected) {
finish();
}
}
function test()
{
waitForExplicitFinish();
testOpen();
testOpenWithState();
testOpenInvalidState();
testOpenTestFile();
}
function testUniqueName(name)
{
ok(name, "Scratchpad has a uniqueName");
if (lastUniqueName === null) {
lastUniqueName = name;
return;
}
ok(name !== lastUniqueName,
"Unique name for this instance differs from the last one.");
}
function testOpen()
{
openScratchpad(function (win) {
is(win.Scratchpad.filename, undefined, "Default filename is undefined");
isnot(win.Scratchpad.getText(), null, "Default text should not be null");
is(win.Scratchpad.executionContext, win.SCRATCHPAD_CONTEXT_CONTENT,
"Default execution context is content");
testUniqueName(win.Scratchpad.uniqueName);
win.close();
done();
}, {noFocus: true});
}
function testOpenWithState()
{
let state = {
filename: "testfile",
executionContext: 2,
text: "test text"
};
openScratchpad(function (win) {
is(win.Scratchpad.filename, state.filename, "Filename loaded from state");
is(win.Scratchpad.executionContext, state.executionContext, "Execution context loaded from state");
is(win.Scratchpad.getText(), state.text, "Content loaded from state");
testUniqueName(win.Scratchpad.uniqueName);
win.close();
done();
}, {state: state, noFocus: true});
}
function testOpenInvalidState()
{
let win = openScratchpad(null, {state: 7});
ok(!win, "no scratchpad opened if state is not an object");
done();
}
function testOpenTestFile()
{
let win = openScratchpad(function (win) {
ok(win, "scratchpad opened for file open");
try {
win.Scratchpad.importFromFile(
"http://example.com/browser/devtools/client/scratchpad/test/NS_ERROR_ILLEGAL_INPUT.txt",
"silent",
function (aStatus, content) {
let nb = win.document.querySelector("#scratchpad-notificationbox");
is(nb.querySelectorAll("notification").length, 1, "There is just one notification");
let cn = nb.currentNotification;
is(cn.priority, nb.PRIORITY_WARNING_HIGH, "notification priority is correct");
is(cn.value, "file-import-convert-failed", "notification value is corrent");
is(cn.type, "warning", "notification type is correct");
done();
});
ok(true, "importFromFile does not cause exception");
} catch (exception) {
ok(false, "importFromFile causes exception " + DevToolsUtils.safeErrorString(exception));
}
}, {noFocus: true});
}

View file

@ -0,0 +1,39 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const HUDService = require("devtools/client/webconsole/hudservice");
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html;charset=utf8,test Scratchpad." +
"openErrorConsole()";
}
function runTests()
{
Services.obs.addObserver(function observer(aSubject) {
Services.obs.removeObserver(observer, "web-console-created");
aSubject.QueryInterface(Ci.nsISupportsString);
let hud = HUDService.getBrowserConsole();
ok(hud, "browser console is open");
is(aSubject.data, hud.hudId, "notification hudId is correct");
HUDService.toggleBrowserConsole().then(finish);
}, "web-console-created", false);
let hud = HUDService.getBrowserConsole();
ok(!hud, "browser console is not open");
info("wait for the browser console to open from Scratchpad");
gScratchpadWindow.Scratchpad.openErrorConsole();
}

View file

@ -0,0 +1,40 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html;charset=utf8,test Scratchpad pretty print.";
}
var gTabsize;
function runTests(sw)
{
gTabsize = Services.prefs.getIntPref("devtools.editor.tabsize");
Services.prefs.setIntPref("devtools.editor.tabsize", 6);
const space = " ".repeat(6);
const sp = sw.Scratchpad;
sp.setText("function main() { console.log(5); }");
sp.prettyPrint().then(() => {
const prettyText = sp.getText();
ok(prettyText.includes(space));
finish();
}).then(null, error => {
ok(false, error);
});
}
registerCleanupFunction(function () {
Services.prefs.setIntPref("devtools.editor.tabsize", gTabsize);
gTabsize = null;
});

View file

@ -0,0 +1,29 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html;charset=utf8,test Scratchpad pretty print.";
}
function runTests(sw)
{
const sp = sw.Scratchpad;
sp.setText("function main() { console.log(5); }");
sp.prettyPrint().then(() => {
const prettyText = sp.getText();
ok(prettyText.includes("\n"));
finish();
}).then(null, error => {
ok(false, error);
});
}

View file

@ -0,0 +1,78 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html;charset=utf8,"
+ "test Scratchpad pretty print error goto line.";
}
function testJumpToPrettyPrintError(sp, error, remark) {
info("will test jumpToLine after prettyPrint error" + remark);
// CodeMirror lines and columns are 0-based, Scratchpad UI and error
// stack are 1-based.
is(/Invalid regular expression flag \(3:10\)/.test(error), true,
"prettyPrint expects error in editor text:\n" + error);
sp.editor.jumpToLine();
const editorDoc = sp.editor.container.contentDocument;
const lineInput = editorDoc.querySelector("input");
const errorLocation = lineInput.value;
const [ inputLine, inputColumn ] = errorLocation.split(":");
const errorLine = 3, errorColumn = 10;
is(inputLine, errorLine,
"jumpToLine input field is set from editor selection (line)");
is(inputColumn, errorColumn,
"jumpToLine input field is set from editor selection (column)");
EventUtils.synthesizeKey("VK_RETURN", { }, editorDoc.defaultView);
// CodeMirror lines and columns are 0-based, Scratchpad UI and error
// stack are 1-based.
const cursor = sp.editor.getCursor();
is(inputLine, cursor.line + 1, "jumpToLine goto error location (line)");
is(inputColumn, cursor.ch + 1, "jumpToLine goto error location (column)");
}
function runTests(sw, sp)
{
sp.setText([
"// line 1",
"// line 2",
"var re = /a bad /regexp/; // line 3 is an obvious syntax error!",
"// line 4",
"// line 5",
""
].join("\n"));
sp.prettyPrint().then(aFulfill => {
ok(false, "Expecting Invalid regexp flag (3:10)");
finish();
}, error => {
testJumpToPrettyPrintError(sp, error, " (Bug 1005471, first time)");
});
sp.prettyPrint().then(aFulfill => {
ok(false, "Expecting Invalid regexp flag (3:10)");
finish();
}, error => {
// Second time verifies bug in earlier implementation fixed.
testJumpToPrettyPrintError(sp, error, " (second time)");
finish();
});
}

View file

@ -0,0 +1,350 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 651942 */
// Reference to the Scratchpad object.
var gScratchpad;
// References to the temporary nsIFiles.
var gFile01;
var gFile02;
var gFile03;
var gFile04;
// lists of recent files.
var lists = {
recentFiles01: null,
recentFiles02: null,
recentFiles03: null,
recentFiles04: null,
};
// Temporary file names.
var gFileName01 = "file01_ForBug651942.tmp";
var gFileName02 = "☕"; // See bug 783858 for more information
var gFileName03 = "file03_ForBug651942.tmp";
var gFileName04 = "file04_ForBug651942.tmp";
// Content for the temporary files.
var gFileContent;
var gFileContent01 = "hello.world.01('bug651942');";
var gFileContent02 = "hello.world.02('bug651942');";
var gFileContent03 = "hello.world.03('bug651942');";
var gFileContent04 = "hello.world.04('bug651942');";
function startTest()
{
gScratchpad = gScratchpadWindow.Scratchpad;
gFile01 = createAndLoadTemporaryFile(gFile01, gFileName01, gFileContent01);
gFile02 = createAndLoadTemporaryFile(gFile02, gFileName02, gFileContent02);
gFile03 = createAndLoadTemporaryFile(gFile03, gFileName03, gFileContent03);
}
// Test to see if the three files we created in the 'startTest()'-method have
// been added to the list of recent files.
function testAddedToRecent()
{
lists.recentFiles01 = gScratchpad.getRecentFiles();
is(lists.recentFiles01.length, 3,
"Temporary files created successfully and added to list of recent files.");
// Create a 4th file, this should clear the oldest file.
gFile04 = createAndLoadTemporaryFile(gFile04, gFileName04, gFileContent04);
}
// We have opened a 4th file. Test to see if the oldest recent file was removed,
// and that the other files were reordered successfully.
function testOverwriteRecent()
{
lists.recentFiles02 = gScratchpad.getRecentFiles();
is(lists.recentFiles02[0], lists.recentFiles01[1],
"File02 was reordered successfully in the 'recent files'-list.");
is(lists.recentFiles02[1], lists.recentFiles01[2],
"File03 was reordered successfully in the 'recent files'-list.");
isnot(lists.recentFiles02[2], lists.recentFiles01[2],
"File04: was added successfully.");
// Open the oldest recent file.
gScratchpad.openFile(0);
}
// We have opened the "oldest"-recent file. Test to see if it is now the most
// recent file, and that the other files were reordered successfully.
function testOpenOldestRecent()
{
lists.recentFiles03 = gScratchpad.getRecentFiles();
is(lists.recentFiles02[0], lists.recentFiles03[2],
"File04 was reordered successfully in the 'recent files'-list.");
is(lists.recentFiles02[1], lists.recentFiles03[0],
"File03 was reordered successfully in the 'recent files'-list.");
is(lists.recentFiles02[2], lists.recentFiles03[1],
"File02 was reordered successfully in the 'recent files'-list.");
Services.prefs.setIntPref("devtools.scratchpad.recentFilesMax", 0);
}
// The "devtools.scratchpad.recentFilesMax"-preference was set to zero (0).
// This should disable the "Open Recent"-menu by hiding it (this should not
// remove any files from the list). Test to see if it's been hidden.
function testHideMenu()
{
let menu = gScratchpadWindow.document.getElementById("sp-open_recent-menu");
ok(menu.hasAttribute("hidden"), "The menu was hidden successfully.");
Services.prefs.setIntPref("devtools.scratchpad.recentFilesMax", 2);
}
// We have set the recentFilesMax-pref to one (1), this enables the feature,
// removes the two oldest files, rebuilds the menu and removes the
// "hidden"-attribute from it. Test to see if this works.
function testChangedMaxRecent()
{
let menu = gScratchpadWindow.document.getElementById("sp-open_recent-menu");
ok(!menu.hasAttribute("hidden"), "The menu is visible. \\o/");
lists.recentFiles04 = gScratchpad.getRecentFiles();
is(lists.recentFiles04.length, 2,
"Two recent files were successfully removed from the 'recent files'-list");
let doc = gScratchpadWindow.document;
let popup = doc.getElementById("sp-menu-open_recentPopup");
let menuitemLabel = popup.children[0].getAttribute("label");
let correctMenuItem = false;
if (menuitemLabel === lists.recentFiles03[2] &&
menuitemLabel === lists.recentFiles04[1]) {
correctMenuItem = true;
}
is(correctMenuItem, true,
"Two recent files were successfully removed from the 'Open Recent'-menu");
// We now remove one file from the harddrive and use the recent-menuitem for
// it to make sure the user is notified that the file no longer exists.
// This is tested in testOpenDeletedFile().
gFile04.remove(false);
// Make sure the file has been deleted before continuing to avoid
// intermittent oranges.
waitForFileDeletion();
}
function waitForFileDeletion() {
if (gFile04.exists()) {
executeSoon(waitForFileDeletion);
return;
}
gFile04 = null;
gScratchpad.openFile(0);
}
// By now we should have two recent files stored in the list but one of the
// files should be missing on the harddrive.
function testOpenDeletedFile() {
let doc = gScratchpadWindow.document;
let popup = doc.getElementById("sp-menu-open_recentPopup");
is(gScratchpad.getRecentFiles().length, 1,
"The missing file was successfully removed from the list.");
// The number of recent files stored, plus the separator and the
// clearRecentMenuItems-item.
is(popup.children.length, 3,
"The missing file was successfully removed from the menu.");
ok(gScratchpad.notificationBox.currentNotification,
"The notification was successfully displayed.");
is(gScratchpad.notificationBox.currentNotification.label,
gScratchpad.strings.GetStringFromName("fileNoLongerExists.notification"),
"The notification label is correct.");
gScratchpad.clearRecentFiles();
}
// We have cleared the last file. Test to see if the last file was removed,
// the menu is empty and was disabled successfully.
function testClearedAll()
{
let doc = gScratchpadWindow.document;
let menu = doc.getElementById("sp-open_recent-menu");
let popup = doc.getElementById("sp-menu-open_recentPopup");
is(gScratchpad.getRecentFiles().length, 0,
"All recent files removed successfully.");
is(popup.children.length, 0, "All menuitems removed successfully.");
ok(menu.hasAttribute("disabled"),
"No files in the menu, it was disabled successfully.");
finishTest();
}
function createAndLoadTemporaryFile(aFile, aFileName, aFileContent)
{
// Create a temporary file.
aFile = FileUtils.getFile("TmpD", [aFileName]);
aFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
// Write the temporary file.
let fout = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
fout.init(aFile.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
0o644, fout.DEFER_OPEN);
gScratchpad.setFilename(aFile.path);
gScratchpad.importFromFile(aFile.QueryInterface(Ci.nsILocalFile), true,
fileImported);
gScratchpad.saveFile(fileSaved);
return aFile;
}
function fileImported(aStatus)
{
ok(Components.isSuccessCode(aStatus),
"the temporary file was imported successfully with Scratchpad");
}
function fileSaved(aStatus)
{
ok(Components.isSuccessCode(aStatus),
"the temporary file was saved successfully with Scratchpad");
checkIfMenuIsPopulated();
}
function checkIfMenuIsPopulated()
{
let doc = gScratchpadWindow.document;
let expectedMenuitemCount = doc.getElementById("sp-menu-open_recentPopup").
children.length;
// The number of recent files stored, plus the separator and the
// clearRecentMenuItems-item.
let recentFilesPlusExtra = gScratchpad.getRecentFiles().length + 2;
if (expectedMenuitemCount > 2) {
is(expectedMenuitemCount, recentFilesPlusExtra,
"the recent files menu was populated successfully.");
}
}
/**
* The PreferenceObserver listens for preference changes while Scratchpad is
* running.
*/
var PreferenceObserver = {
_initialized: false,
_timesFired: 0,
set timesFired(aNewValue) {
this._timesFired = aNewValue;
},
get timesFired() {
return this._timesFired;
},
init: function PO_init()
{
if (this._initialized) {
return;
}
this.branch = Services.prefs.getBranch("devtools.scratchpad.");
this.branch.addObserver("", this, false);
this._initialized = true;
},
observe: function PO_observe(aMessage, aTopic, aData)
{
if (aTopic != "nsPref:changed") {
return;
}
switch (this.timesFired) {
case 0:
this.timesFired = 1;
break;
case 1:
this.timesFired = 2;
break;
case 2:
this.timesFired = 3;
testAddedToRecent();
break;
case 3:
this.timesFired = 4;
testOverwriteRecent();
break;
case 4:
this.timesFired = 5;
testOpenOldestRecent();
break;
case 5:
this.timesFired = 6;
testHideMenu();
break;
case 6:
this.timesFired = 7;
testChangedMaxRecent();
break;
case 7:
this.timesFired = 8;
testOpenDeletedFile();
break;
case 8:
this.timesFired = 9;
testClearedAll();
break;
}
},
uninit: function PO_uninit() {
this.branch.removeObserver("", this);
}
};
function test()
{
waitForExplicitFinish();
registerCleanupFunction(function () {
gFile01.remove(false);
gFile01 = null;
gFile02.remove(false);
gFile02 = null;
gFile03.remove(false);
gFile03 = null;
// gFile04 was removed earlier.
lists.recentFiles01 = null;
lists.recentFiles02 = null;
lists.recentFiles03 = null;
lists.recentFiles04 = null;
gScratchpad = null;
PreferenceObserver.uninit();
Services.prefs.clearUserPref("devtools.scratchpad.recentFilesMax");
});
Services.prefs.setIntPref("devtools.scratchpad.recentFilesMax", 3);
// Initiate the preference observer after we have set the temporary recent
// files max for this test.
PreferenceObserver.init();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(startTest);
}, true);
content.location = "data:text/html,<p>test recent files in Scratchpad";
}
function finishTest()
{
finish();
}

View file

@ -0,0 +1,76 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 740948 */
var DEVTOOLS_CHROME_ENABLED = "devtools.chrome.enabled";
var EDITOR_TEXT = [
"var evt = new CustomEvent('foo', { bubbles: true });",
"document.body.innerHTML = 'Modified text';",
"window.dispatchEvent(evt);"
].join("\n");
function test()
{
requestLongerTimeout(2);
waitForExplicitFinish();
Services.prefs.setBoolPref(DEVTOOLS_CHROME_ENABLED, true);
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,Scratchpad test for bug 740948";
}
function runTests()
{
let sp = gScratchpadWindow.Scratchpad;
ok(sp, "Scratchpad object exists in new window");
// Test that Reload And Run command is enabled in the content
// context and disabled in the browser context.
let reloadAndRun = gScratchpadWindow.document.
getElementById("sp-cmd-reloadAndRun");
ok(reloadAndRun, "Reload And Run command exists");
ok(!reloadAndRun.hasAttribute("disabled"),
"Reload And Run command is enabled");
sp.setBrowserContext();
ok(reloadAndRun.hasAttribute("disabled"),
"Reload And Run command is disabled in the browser context.");
// Switch back to the content context and run our predefined
// code. This code modifies the body of our document and dispatches
// a custom event 'foo'. We listen to that event and check the
// body to make sure that the page has been reloaded and Scratchpad
// code has been executed.
sp.setContentContext();
sp.setText(EDITOR_TEXT);
let browser = gBrowser.selectedBrowser;
let deferred = promise.defer();
browser.addEventListener("DOMWindowCreated", function onWindowCreated() {
browser.removeEventListener("DOMWindowCreated", onWindowCreated, true);
browser.contentWindow.addEventListener("foo", function onFoo() {
browser.contentWindow.removeEventListener("foo", onFoo, true);
is(browser.contentWindow.document.body.innerHTML, "Modified text",
"After reloading, HTML is different.");
Services.prefs.clearUserPref(DEVTOOLS_CHROME_ENABLED);
deferred.resolve();
}, true);
}, true);
ok(browser.contentWindow.document.body.innerHTML !== "Modified text",
"Before reloading, HTML is intact.");
sp.reloadAndRun().then(deferred.promise).then(finish);
}

View file

@ -0,0 +1,65 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 1140839 */
// Test that view menu items are remembered across scratchpad invocations.
function test()
{
waitForExplicitFinish();
// To test for this bug we open a Scratchpad window and change all
// view menu options. After each change we compare the correspondent
// preference value with the expected value.
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,<title>Bug 1140839</title>" +
"<p>test Scratchpad should remember View options";
}
function runTests()
{
let sp = gScratchpadWindow.Scratchpad;
let doc = gScratchpadWindow.document;
let testData = [
{itemMenuId: "sp-menu-line-numbers", prefId: "devtools.scratchpad.lineNumbers", expectedVal: false},
{itemMenuId: "sp-menu-word-wrap", prefId: "devtools.scratchpad.wrapText", expectedVal: true},
{itemMenuId: "sp-menu-highlight-trailing-space", prefId: "devtools.scratchpad.showTrailingSpace", expectedVal: true},
{itemMenuId: "sp-menu-larger-font", prefId: "devtools.scratchpad.editorFontSize", expectedVal: 13},
{itemMenuId: "sp-menu-normal-size-font", prefId: "devtools.scratchpad.editorFontSize", expectedVal: 12},
{itemMenuId: "sp-menu-smaller-font", prefId: "devtools.scratchpad.editorFontSize", expectedVal: 11},
];
testData.forEach(function (data) {
let getPref = getPrefFunction(data.prefId);
try {
let menu = doc.getElementById(data.itemMenuId);
menu.doCommand();
let newPreferenceValue = getPref(data.prefId);
ok(newPreferenceValue === data.expectedVal, newPreferenceValue + " !== " + data.expectedVal);
Services.prefs.clearUserPref(data.prefId);
}
catch (exception) {
ok(false, "Exception thrown while executing the command of menuitem #" + data.itemMenuId);
}
});
finish();
}
function getPrefFunction(preferenceId)
{
let preferenceType = Services.prefs.getPrefType(preferenceId);
if (preferenceType === Services.prefs.PREF_INT) {
return Services.prefs.getIntPref;
} else if (preferenceType === Services.prefs.PREF_BOOL) {
return Services.prefs.getBoolPref;
}
}

View file

@ -0,0 +1,155 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 684546 */
// Reference to the Scratchpad chrome window object.
var gScratchpadWindow;
// Reference to the Scratchpad object.
var gScratchpad;
// Reference to the temporary nsIFile we will work with.
var gFileA;
var gFileB;
// The temporary file content.
var gFileAContent = "// File A ** Hello World!";
var gFileBContent = "// File B ** Goodbye All";
// Help track if one or both files are saved
var gFirstFileSaved = false;
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function browserLoad() {
gBrowser.selectedBrowser.removeEventListener("load", browserLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,<p>test that undo get's reset after file load in Scratchpad";
}
function runTests()
{
gScratchpad = gScratchpadWindow.Scratchpad;
// Create a temporary file.
gFileA = FileUtils.getFile("TmpD", ["fileAForBug684546.tmp"]);
gFileA.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
gFileB = FileUtils.getFile("TmpD", ["fileBForBug684546.tmp"]);
gFileB.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
// Write the temporary file.
let foutA = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
foutA.init(gFileA.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
0o644, foutA.DEFER_OPEN);
let foutB = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
foutB.init(gFileB.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
0o644, foutB.DEFER_OPEN);
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
let fileContentStreamA = converter.convertToInputStream(gFileAContent);
let fileContentStreamB = converter.convertToInputStream(gFileBContent);
NetUtil.asyncCopy(fileContentStreamA, foutA, tempFileSaved);
NetUtil.asyncCopy(fileContentStreamB, foutB, tempFileSaved);
}
function tempFileSaved(aStatus)
{
let success = Components.isSuccessCode(aStatus);
ok(success, "a temporary file was saved successfully");
if (!success)
{
finish();
return;
}
if (gFirstFileSaved && success)
{
ok((gFirstFileSaved && success), "Both files loaded");
// Import the file A into Scratchpad.
gScratchpad.importFromFile(gFileA.QueryInterface(Ci.nsILocalFile), true,
fileAImported);
}
gFirstFileSaved = success;
}
function fileAImported(aStatus, aFileContent)
{
ok(Components.isSuccessCode(aStatus),
"the temporary file A was imported successfully with Scratchpad");
is(aFileContent, gFileAContent, "received data is correct");
is(gScratchpad.getText(), gFileAContent, "the editor content is correct");
gScratchpad.editor.replaceText("new text",
gScratchpad.editor.getPosition(gScratchpad.getText().length));
is(gScratchpad.getText(), gFileAContent + "new text", "text updated correctly");
gScratchpad.undo();
is(gScratchpad.getText(), gFileAContent, "undo works");
gScratchpad.redo();
is(gScratchpad.getText(), gFileAContent + "new text", "redo works");
// Import the file B into Scratchpad.
gScratchpad.importFromFile(gFileB.QueryInterface(Ci.nsILocalFile), true,
fileBImported);
}
function fileBImported(aStatus, aFileContent)
{
ok(Components.isSuccessCode(aStatus),
"the temporary file B was imported successfully with Scratchpad");
is(aFileContent, gFileBContent, "received data is correct");
is(gScratchpad.getText(), gFileBContent, "the editor content is correct");
ok(!gScratchpad.editor.canUndo(), "editor cannot undo after load");
gScratchpad.undo();
is(gScratchpad.getText(), gFileBContent,
"the editor content is still correct after undo");
gScratchpad.editor.replaceText("new text",
gScratchpad.editor.getPosition(gScratchpad.getText().length));
is(gScratchpad.getText(), gFileBContent + "new text", "text updated correctly");
gScratchpad.undo();
is(gScratchpad.getText(), gFileBContent, "undo works");
ok(!gScratchpad.editor.canUndo(), "editor cannot undo after load (again)");
gScratchpad.redo();
is(gScratchpad.getText(), gFileBContent + "new text", "redo works");
// Done!
finish();
}
registerCleanupFunction(function () {
if (gFileA && gFileA.exists())
{
gFileA.remove(false);
gFileA = null;
}
if (gFileB && gFileB.exists())
{
gFileB.remove(false);
gFileB = null;
}
gScratchpad = null;
});

View file

@ -0,0 +1,96 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Call the iterator for each item in the list,
calling the final callback with all the results
after every iterator call has sent its result */
function asyncMap(items, iterator, callback)
{
let expected = items.length;
let results = [];
items.forEach(function (item) {
iterator(item, function (result) {
results.push(result);
if (results.length == expected) {
callback(results);
}
});
});
}
function test()
{
waitForExplicitFinish();
testRestore();
}
function testRestore()
{
let states = [
{
filename: "testfile",
text: "test1",
executionContext: 2
},
{
text: "text2",
executionContext: 1
},
{
text: "text3",
executionContext: 1
}
];
asyncMap(states, function (state, done) {
// Open some scratchpad windows
openScratchpad(done, {state: state, noFocus: true});
}, function (wins) {
// Then save the windows to session store
ScratchpadManager.saveOpenWindows();
// Then get their states
let session = ScratchpadManager.getSessionState();
// Then close them
wins.forEach(function (win) {
win.close();
});
// Clear out session state for next tests
ScratchpadManager.saveOpenWindows();
// Then restore them
let restoredWins = ScratchpadManager.restoreSession(session);
is(restoredWins.length, 3, "Three scratchad windows restored");
asyncMap(restoredWins, function (restoredWin, done) {
openScratchpad(function (aWin) {
let state = aWin.Scratchpad.getState();
aWin.close();
done(state);
}, {window: restoredWin, noFocus: true});
}, function (restoredStates) {
// Then make sure they were restored with the right states
ok(statesMatch(restoredStates, states),
"All scratchpad window states restored correctly");
// Yay, we're done!
finish();
});
});
}
function statesMatch(restoredStates, states)
{
return states.every(function (state) {
return restoredStates.some(function (restoredState) {
return state.filename == restoredState.filename
&& state.text == restoredState.text
&& state.executionContext == restoredState.executionContext;
});
});
}

View file

@ -0,0 +1,134 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 751744 */
// Reference to the Scratchpad object.
var gScratchpad;
// Reference to the temporary nsIFiles.
var gFile;
// Temporary file name.
var gFileName = "testFileForBug751744.tmp";
// Content for the temporary file.
var gFileContent = "/* this file is already saved */\n" +
"function foo() { alert('bar') }";
var gLength = gFileContent.length;
// Reference to the menu entry.
var menu;
function startTest()
{
gScratchpad = gScratchpadWindow.Scratchpad;
menu = gScratchpadWindow.document.getElementById("sp-cmd-revert");
createAndLoadTemporaryFile();
}
function testAfterSaved() {
// Check if the revert menu is disabled as the file is at saved state.
ok(menu.hasAttribute("disabled"), "The revert menu entry is disabled.");
// chancging the text in the file
gScratchpad.setText(gScratchpad.getText() + "\nfoo();");
// Checking the text got changed
is(gScratchpad.getText(), gFileContent + "\nfoo();",
"The text changed the first time.");
// Revert menu now should be enabled.
ok(!menu.hasAttribute("disabled"),
"The revert menu entry is enabled after changing text first time");
// reverting back to last saved state.
gScratchpad.revertFile(testAfterRevert);
}
function testAfterRevert() {
// Check if the file's text got reverted
is(gScratchpad.getText(), gFileContent,
"The text reverted back to original text.");
// The revert menu should be disabled again.
ok(menu.hasAttribute("disabled"),
"The revert menu entry is disabled after reverting.");
// chancging the text in the file again
gScratchpad.setText(gScratchpad.getText() + "\nalert(foo.toSource());");
// Saving the file.
gScratchpad.saveFile(testAfterSecondSave);
}
function testAfterSecondSave() {
// revert menu entry should be disabled.
ok(menu.hasAttribute("disabled"),
"The revert menu entry is disabled after saving.");
// changing the text.
gScratchpad.setText(gScratchpad.getText() + "\nfoo();");
// revert menu entry should get enabled yet again.
ok(!menu.hasAttribute("disabled"),
"The revert menu entry is enabled after changing text third time");
// reverting back to last saved state.
gScratchpad.revertFile(testAfterSecondRevert);
}
function testAfterSecondRevert() {
// Check if the file's text got reverted
is(gScratchpad.getText(), gFileContent + "\nalert(foo.toSource());",
"The text reverted back to the changed saved text.");
// The revert menu should be disabled again.
ok(menu.hasAttribute("disabled"),
"Revert menu entry is disabled after reverting to changed saved state.");
gFile.remove(false);
gFile = gScratchpad = menu = null;
finish();
}
function createAndLoadTemporaryFile()
{
// Create a temporary file.
gFile = FileUtils.getFile("TmpD", [gFileName]);
gFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
// Write the temporary file.
let fout = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
fout.init(gFile.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
0o644, fout.DEFER_OPEN);
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
let fileContentStream = converter.convertToInputStream(gFileContent);
NetUtil.asyncCopy(fileContentStream, fout, tempFileSaved);
}
function tempFileSaved(aStatus)
{
ok(Components.isSuccessCode(aStatus),
"the temporary file was saved successfully");
// Import the file into Scratchpad.
gScratchpad.setFilename(gFile.path);
gScratchpad.importFromFile(gFile.QueryInterface(Ci.nsILocalFile), true,
testAfterSaved);
}
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(startTest);
}, true);
content.location = "data:text/html,<p>test reverting to last saved state of" +
" a file </p>";
}

View file

@ -0,0 +1,60 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html;charset=utf8,test Scratchpad pretty print.";
}
function runTests(sw)
{
const sp = sw.Scratchpad;
sp.setText([
"// line 1",
"// line 2",
"var re = /a bad /regexp/; // line 3 is an obvious syntax error!",
"// line 4",
"// line 5",
""
].join("\n"));
sp.run().then(() => {
// CodeMirror lines and columns are 0-based, Scratchpad UI and error
// stack are 1-based.
let errorLine = 3;
let editorDoc = sp.editor.container.contentDocument;
sp.editor.jumpToLine();
let lineInput = editorDoc.querySelector("input");
let inputLine = lineInput.value;
is(inputLine, errorLine, "jumpToLine input field is set from editor selection");
EventUtils.synthesizeKey("VK_RETURN", { }, editorDoc.defaultView);
// CodeMirror lines and columns are 0-based, Scratchpad UI and error
// stack are 1-based.
let cursor = sp.editor.getCursor();
is(cursor.line + 1, inputLine, "jumpToLine goto error location (line)");
is(cursor.ch + 1, 1, "jumpToLine goto error location (column)");
}, error => {
ok(false, error);
finish();
}).then(() => {
var statusBarField = sp.editor.container.ownerDocument.querySelector("#statusbar-line-col");
let { line, ch } = sp.editor.getCursor();
is(statusBarField.textContent, sp.strings.formatStringFromName(
"scratchpad.statusBarLineCol", [ line + 1, ch + 1], 2), "statusbar text is correct (" + statusBarField.textContent + ")");
finish();
}, error => {
ok(false, error);
finish();
});
}

View file

@ -0,0 +1,75 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 660560 */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onTabLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onTabLoad, true);
Services.prefs.setIntPref("devtools.editor.tabsize", 5);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,Scratchpad test for the Tab key, bug 660560";
}
function runTests()
{
let sp = gScratchpadWindow.Scratchpad;
ok(sp, "Scratchpad object exists in new window");
ok(sp.editor.hasFocus(), "the editor has focus");
sp.setText("window.foo;");
sp.editor.setCursor({ line: 0, ch: 0 });
EventUtils.synthesizeKey("VK_TAB", {}, gScratchpadWindow);
is(sp.getText(), " window.foo;", "Tab key added 5 spaces");
is(sp.editor.getCursor().line, 0, "line is correct");
is(sp.editor.getCursor().ch, 5, "character is correct");
sp.editor.setCursor({ line: 0, ch: 6 });
EventUtils.synthesizeKey("VK_TAB", {}, gScratchpadWindow);
is(sp.getText(), " w indow.foo;",
"Tab key added 4 spaces");
is(sp.editor.getCursor().line, 0, "line is correct");
is(sp.editor.getCursor().ch, 10, "character is correct");
gScratchpadWindow.close();
Services.prefs.setIntPref("devtools.editor.tabsize", 6);
Services.prefs.setBoolPref("devtools.editor.expandtab", false);
openScratchpad(runTests2);
}
function runTests2()
{
let sp = gScratchpadWindow.Scratchpad;
sp.setText("window.foo;");
sp.editor.setCursor({ line: 0, ch: 0 });
EventUtils.synthesizeKey("VK_TAB", {}, gScratchpadWindow);
is(sp.getText(), "\twindow.foo;", "Tab key added the tab character");
is(sp.editor.getCursor().line, 0, "line is correct");
is(sp.editor.getCursor().ch, 1, "character is correct");
Services.prefs.clearUserPref("devtools.editor.tabsize");
Services.prefs.clearUserPref("devtools.editor.expandtab");
finish();
}

View file

@ -0,0 +1,103 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
var tab1;
var tab2;
var sp;
function test()
{
waitForExplicitFinish();
tab1 = gBrowser.addTab();
gBrowser.selectedTab = tab1;
gBrowser.selectedBrowser.addEventListener("load", function onLoad1() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad1, true);
tab2 = gBrowser.addTab();
gBrowser.selectedTab = tab2;
gBrowser.selectedBrowser.addEventListener("load", function onLoad2() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad2, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,test context switch in Scratchpad tab 2";
}, true);
content.location = "data:text/html,test context switch in Scratchpad tab 1";
}
function runTests()
{
sp = gScratchpadWindow.Scratchpad;
let contentMenu = gScratchpadWindow.document.getElementById("sp-menu-content");
let browserMenu = gScratchpadWindow.document.getElementById("sp-menu-browser");
let notificationBox = sp.notificationBox;
ok(contentMenu, "found #sp-menu-content");
ok(browserMenu, "found #sp-menu-browser");
ok(notificationBox, "found Scratchpad.notificationBox");
sp.setContentContext();
is(sp.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_CONTENT,
"executionContext is content");
is(contentMenu.getAttribute("checked"), "true",
"content menuitem is checked");
isnot(browserMenu.getAttribute("checked"), "true",
"chrome menuitem is not checked");
is(notificationBox.currentNotification, null,
"there is no notification currently shown for content context");
sp.setText("window.foosbug653108 = 'aloha';");
ok(!content.wrappedJSObject.foosbug653108,
"no content.foosbug653108");
sp.run().then(function () {
is(content.wrappedJSObject.foosbug653108, "aloha",
"content.foosbug653108 has been set");
gBrowser.tabContainer.addEventListener("TabSelect", runTests2, true);
gBrowser.selectedTab = tab1;
});
}
function runTests2() {
gBrowser.tabContainer.removeEventListener("TabSelect", runTests2, true);
ok(!window.foosbug653108, "no window.foosbug653108");
sp.setText("window.foosbug653108");
sp.run().then(function ([, , result]) {
isnot(result, "aloha", "window.foosbug653108 is not aloha");
sp.setText("window.foosbug653108 = 'ahoyhoy';");
sp.run().then(function () {
is(content.wrappedJSObject.foosbug653108, "ahoyhoy",
"content.foosbug653108 has been set 2");
gBrowser.selectedBrowser.addEventListener("load", runTests3, true);
content.location = "data:text/html,test context switch in Scratchpad location 2";
});
});
}
function runTests3() {
gBrowser.selectedBrowser.removeEventListener("load", runTests3, true);
// Check that the sandbox is not cached.
sp.setText("typeof foosbug653108;");
sp.run().then(function ([, , result]) {
is(result, "undefined", "global variable does not exist");
tab1 = null;
tab2 = null;
sp = null;
finish();
});
}

View file

@ -0,0 +1,52 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(testThrowOutput);
}, true);
content.location = "data:text/html;charset=utf8,<p>Test throw outputs in Scratchpad</p>";
}
function testThrowOutput()
{
let scratchpad = gScratchpadWindow.Scratchpad, tests = [];
let falsyValues = ["false", "0", "-0", "null", "undefined", "Infinity",
"-Infinity", "NaN"];
falsyValues.forEach(function (value) {
tests.push({
method: "display",
code: "throw " + value + ";",
result: "throw " + value + ";\n/*\nException: " + value + "\n*/",
label: "Correct exception message for '" + value + "' is shown"
});
});
let { DebuggerServer } = require("devtools/server/main");
let longLength = DebuggerServer.LONG_STRING_LENGTH + 1;
let longString = new Array(longLength).join("a");
let shortedString = longString.substring(0,
DebuggerServer.LONG_STRING_INITIAL_LENGTH) + "\u2026";
tests.push({
method: "display",
code: "throw (new Array(" + longLength + ").join('a'));",
result: "throw (new Array(" + longLength + ").join('a'));\n" +
"/*\nException: " + shortedString + "\n*/",
label: "Correct exception message for a longString is shown"
});
runAsyncTests(scratchpad, tests).then(function () {
finish();
});
}

View file

@ -0,0 +1,74 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(runTests);
}, true);
content.location = "data:text/html,<title>foobarBug636725</title>" +
"<p>test inspect() in Scratchpad";
}
function runTests()
{
let sp = gScratchpadWindow.Scratchpad;
let doc = gScratchpadWindow.document;
let methodsAndItems = {
"sp-menu-newscratchpad": "openScratchpad",
"sp-menu-open": "openFile",
"sp-menu-save": "saveFile",
"sp-menu-saveas": "saveFileAs",
"sp-text-run": "run",
"sp-text-inspect": "inspect",
"sp-text-display": "display",
"sp-text-reloadAndRun": "reloadAndRun",
"sp-menu-content": "setContentContext",
"sp-menu-browser": "setBrowserContext",
"sp-menu-pprint": "prettyPrint",
"sp-menu-line-numbers": "toggleEditorOption",
"sp-menu-word-wrap": "toggleEditorOption",
"sp-menu-highlight-trailing-space": "toggleEditorOption",
"sp-menu-larger-font": "increaseFontSize",
"sp-menu-smaller-font": "decreaseFontSize",
"sp-menu-normal-size-font": "normalFontSize",
};
let lastMethodCalled = null;
for (let id in methodsAndItems) {
lastMethodCalled = null;
let methodName = methodsAndItems[id];
let oldMethod = sp[methodName];
ok(oldMethod, "found method " + methodName + " in Scratchpad object");
sp[methodName] = () => {
lastMethodCalled = methodName;
};
let menu = doc.getElementById(id);
ok(menu, "found menuitem #" + id);
try {
menu.doCommand();
}
catch (ex) {
ok(false, "exception thrown while executing the command of menuitem #" + id);
}
ok(lastMethodCalled == methodName,
"method " + methodName + " invoked by the associated menuitem");
sp[methodName] = oldMethod;
}
finish();
}

View file

@ -0,0 +1,119 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 669612 */
// only finish() when correct number of tests are done
const expected = 4;
var count = 0;
function done()
{
if (++count == expected) {
finish();
}
}
function test()
{
waitForExplicitFinish();
testListeners();
testRestoreNotFromFile();
testRestoreFromFileSaved();
testRestoreFromFileUnsaved();
gBrowser.selectedTab = gBrowser.addTab();
content.location = "data:text/html,<p>test star* UI for unsaved file changes";
}
function testListeners()
{
openScratchpad(function (aWin, aScratchpad) {
aScratchpad.setText("new text");
ok(isStar(aWin), "show star if scratchpad text changes");
aScratchpad.dirty = false;
ok(!isStar(aWin), "no star before changing text");
aScratchpad.setFilename("foo.js");
aScratchpad.setText("new text2");
ok(isStar(aWin), "shows star if scratchpad text changes");
aScratchpad.dirty = false;
ok(!isStar(aWin), "no star if scratchpad was just saved");
aScratchpad.setText("new text3");
ok(isStar(aWin), "shows star if scratchpad has more changes");
aScratchpad.undo();
ok(!isStar(aWin), "no star if scratchpad undo to save point");
aScratchpad.undo();
ok(isStar(aWin), "star if scratchpad undo past save point");
aWin.close();
done();
}, {noFocus: true});
}
function testRestoreNotFromFile()
{
let session = [{
text: "test1",
executionContext: 1
}];
let [win] = ScratchpadManager.restoreSession(session);
openScratchpad(function (aWin, aScratchpad) {
aScratchpad.setText("new text");
ok(isStar(win), "show star if restored scratchpad isn't from a file");
win.close();
done();
}, {window: win, noFocus: true});
}
function testRestoreFromFileSaved()
{
let session = [{
filename: "test.js",
text: "test1",
executionContext: 1,
saved: true
}];
let [win] = ScratchpadManager.restoreSession(session);
openScratchpad(function (aWin, aScratchpad) {
ok(!isStar(win), "no star before changing text in scratchpad restored from file");
aScratchpad.setText("new text");
ok(isStar(win), "star when text changed from scratchpad restored from file");
win.close();
done();
}, {window: win, noFocus: true});
}
function testRestoreFromFileUnsaved()
{
let session = [{
filename: "test.js",
text: "test1",
executionContext: 1,
saved: false
}];
let [win] = ScratchpadManager.restoreSession(session);
openScratchpad(function () {
ok(isStar(win), "star with scratchpad restored with unsaved text");
win.close();
done();
}, {window: win, noFocus: true});
}
function isStar(win)
{
return win.document.title.match(/^\*[^\*]/);
}

View file

@ -0,0 +1,93 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Bug 661762 */
// Use the old webconsole since scratchpad focus isn't working on new one (Bug 1304794)
Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
registerCleanupFunction(function* () {
Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
});
function test()
{
waitForExplicitFinish();
// To test for this bug we open a Scratchpad window, save its
// reference and then open another one. This way the first window
// loses its focus.
//
// Then we open a web console and execute a console.log statement
// from the first Scratch window (that's why we needed to save its
// reference).
//
// Then we wait for our message to appear in the console and click
// on the location link. After that we check which Scratchpad window
// is currently active (it should be the older one).
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(function () {
let sw = gScratchpadWindow;
let {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
let {TargetFactory} = require("devtools/client/framework/target");
openScratchpad(function () {
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "webconsole").then((toolbox) => {
let hud = toolbox.getCurrentPanel().hud;
hud.jsterm.clearOutput(true);
testFocus(sw, hud);
});
});
});
}, true);
content.location = "data:text/html;charset=utf8,<p>test window focus for Scratchpad.";
}
function testFocus(sw, hud) {
let sp = sw.Scratchpad;
function onMessage(event, messages) {
let msg = [...messages][0];
let node = msg.node;
var loc = node.querySelector(".frame-link");
ok(loc, "location element exists");
is(loc.getAttribute("data-url"), sw.Scratchpad.uniqueName, "location value is correct");
is(loc.getAttribute("data-line"), "1", "line value is correct");
is(loc.getAttribute("data-column"), "1", "column value is correct");
sw.addEventListener("focus", function onFocus() {
sw.removeEventListener("focus", onFocus, true);
let win = Services.wm.getMostRecentWindow("devtools:scratchpad");
ok(win, "there are active Scratchpad windows");
is(win.Scratchpad.uniqueName, sw.Scratchpad.uniqueName,
"correct window is in focus");
// gScratchpadWindow will be closed automatically but we need to
// close the second window ourselves.
sw.close();
finish();
}, true);
// Simulate a click on the "Scratchpad/N:1" link.
EventUtils.synthesizeMouse(loc, 2, 2, {}, hud.iframeWindow);
}
// Sending messages to web console is an asynchronous operation. That's
// why we have to setup an observer here.
hud.ui.once("new-messages", onMessage);
sp.setText("console.log('foo');");
sp.run().then(function ([selection, error, result]) {
is(selection, "console.log('foo');", "selection is correct");
is(error, undefined, "error is correct");
is(result.type, "undefined", "result is correct");
});
}

View file

@ -0,0 +1,221 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {});
const {console} = Cu.import("resource://gre/modules/Console.jsm", {});
const {ScratchpadManager} = Cu.import("resource://devtools/client/scratchpad/scratchpad-manager.jsm", {});
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
const Services = require("Services");
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
const flags = require("devtools/shared/flags");
const promise = require("promise");
var gScratchpadWindow; // Reference to the Scratchpad chrome window object
flags.testing = true;
SimpleTest.registerCleanupFunction(() => {
flags.testing = false;
});
/**
* Open a Scratchpad window.
*
* @param function aReadyCallback
* Optional. The function you want invoked when the Scratchpad instance
* is ready.
* @param object aOptions
* Optional. Options for opening the scratchpad:
* - window
* Provide this if there's already a Scratchpad window you want to wait
* loading for.
* - state
* Scratchpad state object. This is used when Scratchpad is open.
* - noFocus
* Boolean that tells you do not want the opened window to receive
* focus.
* @return nsIDOMWindow
* The new window object that holds Scratchpad. Note that the
* gScratchpadWindow global is also updated to reference the new window
* object.
*/
function openScratchpad(aReadyCallback, aOptions = {})
{
let win = aOptions.window ||
ScratchpadManager.openScratchpad(aOptions.state);
if (!win) {
return;
}
let onLoad = function () {
win.removeEventListener("load", onLoad, false);
win.Scratchpad.addObserver({
onReady: function (aScratchpad) {
aScratchpad.removeObserver(this);
if (aOptions.noFocus) {
aReadyCallback(win, aScratchpad);
} else {
waitForFocus(aReadyCallback.bind(null, win, aScratchpad), win);
}
}
});
};
if (aReadyCallback) {
win.addEventListener("load", onLoad, false);
}
gScratchpadWindow = win;
return gScratchpadWindow;
}
/**
* Open a new tab and then open a scratchpad.
* @param object aOptions
* Optional. Options for opening the tab and scratchpad. In addition
* to the options supported by openScratchpad, the following options
* are supported:
* - tabContent
* A string providing the html content of the tab.
* @return Promise
*/
function openTabAndScratchpad(aOptions = {})
{
waitForExplicitFinish();
return new promise(resolve => {
gBrowser.selectedTab = gBrowser.addTab();
let {selectedBrowser} = gBrowser;
selectedBrowser.addEventListener("load", function onLoad() {
selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad((win, sp) => resolve([win, sp]), aOptions);
}, true);
content.location = "data:text/html;charset=utf8," + (aOptions.tabContent || "");
});
}
/**
* Create a temporary file, write to it and call a callback
* when done.
*
* @param string aName
* Name of your temporary file.
* @param string aContent
* Temporary file's contents.
* @param function aCallback
* Optional callback to be called when we're done writing
* to the file. It will receive two parameters: status code
* and a file object.
*/
function createTempFile(aName, aContent, aCallback = function () {})
{
// Create a temporary file.
let file = FileUtils.getFile("TmpD", [aName]);
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("666", 8));
// Write the temporary file.
let fout = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
fout.init(file.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
parseInt("644", 8), fout.DEFER_OPEN);
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
let fileContentStream = converter.convertToInputStream(aContent);
NetUtil.asyncCopy(fileContentStream, fout, function (aStatus) {
aCallback(aStatus, file);
});
}
/**
* Run a set of asychronous tests sequentially defined by input and output.
*
* @param Scratchpad aScratchpad
* The scratchpad to use in running the tests.
* @param array aTests
* An array of test objects, each with the following properties:
* - method
* Scratchpad method to use, one of "run", "display", or "inspect".
* - code
* Code to run in the scratchpad.
* - result
* Expected code that will be in the scratchpad upon completion.
* - label
* The tests label which will be logged in the test runner output.
* @return Promise
* The promise that will be resolved when all tests are finished.
*/
function runAsyncTests(aScratchpad, aTests)
{
let deferred = promise.defer();
(function runTest() {
if (aTests.length) {
let test = aTests.shift();
aScratchpad.setText(test.code);
aScratchpad[test.method]().then(function success() {
is(aScratchpad.getText(), test.result, test.label);
runTest();
}, function failure(error) {
ok(false, error.stack + " " + test.label);
runTest();
});
} else {
deferred.resolve();
}
})();
return deferred.promise;
}
/**
* Run a set of asychronous tests sequentially with callbacks to prepare each
* test and to be called when the test result is ready.
*
* @param Scratchpad aScratchpad
* The scratchpad to use in running the tests.
* @param array aTests
* An array of test objects, each with the following properties:
* - method
* Scratchpad method to use, one of "run", "display", or "inspect".
* - prepare
* The callback to run just prior to executing the scratchpad method.
* - then
* The callback to run when the scratchpad execution promise resolves.
* @return Promise
* The promise that will be resolved when all tests are finished.
*/
var runAsyncCallbackTests = Task.async(function* (aScratchpad, aTests) {
for (let {prepare, method, then} of aTests) {
yield prepare();
let res = yield aScratchpad[method]();
yield then(res);
}
});
/**
* A simple wrapper for ContentTask.spawn for more compact code.
*/
function inContent(generator) {
return ContentTask.spawn(gBrowser.selectedBrowser, {}, generator);
}
function cleanup()
{
if (gScratchpadWindow) {
gScratchpadWindow.close();
gScratchpadWindow = null;
}
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
}
registerCleanupFunction(cleanup);