mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 16:58:38 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
6
devtools/client/styleeditor/test/.eslintrc.js
Normal file
6
devtools/client/styleeditor/test/.eslintrc.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
// Extend from the shared list of defined globals for mochitests.
|
||||
"extends": "../../../.eslintrc.mochitests.js"
|
||||
};
|
||||
23
devtools/client/styleeditor/test/autocomplete.html
Normal file
23
devtools/client/styleeditor/test/autocomplete.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>testcase for autocomplete testing</title>
|
||||
<link rel="stylesheet" type="text/css" href="resources_inpage1.css"/>
|
||||
<style type="text/css">
|
||||
div {
|
||||
font-size: 4em;
|
||||
}
|
||||
|
||||
div > span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div + button {
|
||||
border: 2px dotted red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>parent <span>child</span></div><button>sibling</button>
|
||||
</body>
|
||||
</html>
|
||||
107
devtools/client/styleeditor/test/browser.ini
Normal file
107
devtools/client/styleeditor/test/browser.ini
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
[DEFAULT]
|
||||
tags = devtools
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
autocomplete.html
|
||||
browser_styleeditor_cmd_edit.html
|
||||
four.html
|
||||
head.js
|
||||
import.css
|
||||
import.html
|
||||
import2.css
|
||||
inline-1.html
|
||||
inline-2.html
|
||||
longload.html
|
||||
media-small.css
|
||||
media.html
|
||||
media-rules.html
|
||||
media-rules.css
|
||||
media-rules-sourcemaps.html
|
||||
minified.html
|
||||
missing.html
|
||||
nostyle.html
|
||||
pretty.css
|
||||
resources_inpage.jsi
|
||||
resources_inpage1.css
|
||||
resources_inpage2.css
|
||||
simple.css
|
||||
simple.css.gz
|
||||
simple.css.gz^headers^
|
||||
simple.gz.html
|
||||
simple.html
|
||||
sourcemap-css/contained.css
|
||||
sourcemap-css/sourcemaps.css
|
||||
sourcemap-css/sourcemaps.css.map
|
||||
sourcemap-css/media-rules.css
|
||||
sourcemap-css/media-rules.css.map
|
||||
sourcemap-css/test-bootstrap-scss.css
|
||||
sourcemap-css/test-stylus.css
|
||||
sourcemap-sass/sourcemaps.scss
|
||||
sourcemap-sass/media-rules.scss
|
||||
sourcemap-styl/test-stylus.styl
|
||||
sourcemaps.html
|
||||
sourcemaps-inline.html
|
||||
sourcemaps-large.html
|
||||
sourcemaps-watching.html
|
||||
test_private.css
|
||||
test_private.html
|
||||
doc_long.css
|
||||
doc_uncached.css
|
||||
doc_uncached.html
|
||||
doc_xulpage.xul
|
||||
sync.html
|
||||
utf-16.css
|
||||
!/devtools/client/commandline/test/helpers.js
|
||||
!/devtools/client/framework/test/shared-head.js
|
||||
!/devtools/client/inspector/shared/test/head.js
|
||||
!/devtools/client/inspector/test/head.js
|
||||
!/devtools/client/inspector/test/shared-head.js
|
||||
!/devtools/client/responsive.html/test/browser/devices.json
|
||||
!/devtools/client/shared/test/test-actor-registry.js
|
||||
!/devtools/client/shared/test/test-actor.js
|
||||
|
||||
[browser_styleeditor_autocomplete.js]
|
||||
[browser_styleeditor_autocomplete-disabled.js]
|
||||
[browser_styleeditor_bom.js]
|
||||
[browser_styleeditor_bug_740541_iframes.js]
|
||||
[browser_styleeditor_bug_851132_middle_click.js]
|
||||
[browser_styleeditor_bug_870339.js]
|
||||
[browser_styleeditor_cmd_edit.js]
|
||||
[browser_styleeditor_enabled.js]
|
||||
[browser_styleeditor_fetch-from-cache.js]
|
||||
[browser_styleeditor_filesave.js]
|
||||
[browser_styleeditor_highlight-selector.js]
|
||||
[browser_styleeditor_import.js]
|
||||
[browser_styleeditor_import_rule.js]
|
||||
[browser_styleeditor_init.js]
|
||||
[browser_styleeditor_inline_friendly_names.js]
|
||||
[browser_styleeditor_loading.js]
|
||||
[browser_styleeditor_loading_with_containers.js]
|
||||
[browser_styleeditor_media_sidebar.js]
|
||||
[browser_styleeditor_media_sidebar_links.js]
|
||||
skip-if = e10s && debug # Bug 1252201 - Docshell leak on debug e10s
|
||||
[browser_styleeditor_media_sidebar_sourcemaps.js]
|
||||
[browser_styleeditor_missing_stylesheet.js]
|
||||
[browser_styleeditor_navigate.js]
|
||||
[browser_styleeditor_new.js]
|
||||
[browser_styleeditor_nostyle.js]
|
||||
[browser_styleeditor_opentab.js]
|
||||
[browser_styleeditor_pretty.js]
|
||||
[browser_styleeditor_private_perwindowpb.js]
|
||||
[browser_styleeditor_reload.js]
|
||||
[browser_styleeditor_scroll.js]
|
||||
[browser_styleeditor_sv_keynav.js]
|
||||
[browser_styleeditor_sv_resize.js]
|
||||
[browser_styleeditor_selectstylesheet.js]
|
||||
[browser_styleeditor_sourcemaps.js]
|
||||
[browser_styleeditor_sourcemaps_inline.js]
|
||||
[browser_styleeditor_sourcemap_large.js]
|
||||
[browser_styleeditor_sourcemap_watching.js]
|
||||
[browser_styleeditor_sync.js]
|
||||
[browser_styleeditor_syncAddProperty.js]
|
||||
[browser_styleeditor_syncAddRule.js]
|
||||
[browser_styleeditor_syncAlreadyOpen.js]
|
||||
[browser_styleeditor_syncEditSelector.js]
|
||||
[browser_styleeditor_syncIntoRuleView.js]
|
||||
[browser_styleeditor_transition_rule.js]
|
||||
[browser_styleeditor_xul.js]
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/* 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";
|
||||
|
||||
// Test that autocomplete can be disabled.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "autocomplete.html";
|
||||
|
||||
// Pref which decides if CSS autocompletion is enabled in Style Editor or not.
|
||||
const AUTOCOMPLETION_PREF = "devtools.styleeditor.autocompletion-enabled";
|
||||
|
||||
add_task(function* () {
|
||||
Services.prefs.setBoolPref(AUTOCOMPLETION_PREF, false);
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
let editor = yield ui.editors[0].getSourceEditor();
|
||||
|
||||
is(editor.sourceEditor.getOption("autocomplete"), false,
|
||||
"Autocompletion option does not exist");
|
||||
ok(!editor.sourceEditor.getAutocompletionPopup(),
|
||||
"Autocompletion popup does not exist");
|
||||
});
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref(AUTOCOMPLETION_PREF);
|
||||
});
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
/* 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";
|
||||
|
||||
// Test that autocompletion works as expected.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "autocomplete.html";
|
||||
const MAX_SUGGESTIONS = 15;
|
||||
|
||||
const {initCssProperties} = require("devtools/shared/fronts/css-properties");
|
||||
|
||||
// Test cases to test that autocompletion works correctly when enabled.
|
||||
// Format:
|
||||
// [
|
||||
// key,
|
||||
// {
|
||||
// total: Number of suggestions in the popup (-1 if popup is closed),
|
||||
// current: Index of selected suggestion,
|
||||
// inserted: 1 to check whether the selected suggestion is inserted into the
|
||||
// editor or not,
|
||||
// entered: 1 if the suggestion is inserted and finalized
|
||||
// }
|
||||
// ]
|
||||
|
||||
function getTestCases(cssProperties) {
|
||||
let keywords = getCSSKeywords(cssProperties);
|
||||
let getSuggestionNumberFor = suggestionNumberGetter(keywords);
|
||||
|
||||
return [
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["Ctrl+Space", {total: 1, current: 0}],
|
||||
["VK_LEFT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_DOWN"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["Ctrl+Space", { total: getSuggestionNumberFor("font"), current: 0}],
|
||||
["VK_END"],
|
||||
["VK_RETURN"],
|
||||
["b", {total: getSuggestionNumberFor("b"), current: 0}],
|
||||
["a", {total: getSuggestionNumberFor("ba"), current: 0}],
|
||||
["VK_DOWN", {total: getSuggestionNumberFor("ba"), current: 0, inserted: 1}],
|
||||
["VK_TAB", {total: getSuggestionNumberFor("ba"), current: 1, inserted: 1}],
|
||||
["VK_RETURN", {current: 1, inserted: 1, entered: 1}],
|
||||
["b", {total: getSuggestionNumberFor("background", "b"), current: 0}],
|
||||
["l", {total: getSuggestionNumberFor("background", "bl"), current: 0}],
|
||||
["VK_TAB", {
|
||||
total: getSuggestionNumberFor("background", "bl"),
|
||||
current: 0, inserted: 1
|
||||
}],
|
||||
["VK_DOWN", {
|
||||
total: getSuggestionNumberFor("background", "bl"),
|
||||
current: 1, inserted: 1
|
||||
}],
|
||||
["VK_UP", {
|
||||
total: getSuggestionNumberFor("background", "bl"),
|
||||
current: 0,
|
||||
inserted: 1
|
||||
}],
|
||||
["VK_TAB", {
|
||||
total: getSuggestionNumberFor("background", "bl"),
|
||||
current: 1,
|
||||
inserted: 1
|
||||
}],
|
||||
["VK_TAB", {
|
||||
total: getSuggestionNumberFor("background", "bl"),
|
||||
current: 2,
|
||||
inserted: 1
|
||||
}],
|
||||
[";"],
|
||||
["VK_RETURN"],
|
||||
["c", {total: getSuggestionNumberFor("c"), current: 0}],
|
||||
["o", {total: getSuggestionNumberFor("co"), current: 0}],
|
||||
["VK_RETURN", {current: 0, inserted: 1}],
|
||||
["r", {total: getSuggestionNumberFor("color", "r"), current: 0}],
|
||||
["VK_RETURN", {current: 0, inserted: 1}],
|
||||
[";"],
|
||||
["VK_LEFT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_DOWN"],
|
||||
["VK_RETURN"],
|
||||
["b", {total: 2, current: 0}],
|
||||
["u", {total: 1, current: 0}],
|
||||
["VK_RETURN", {current: 0, inserted: 1}],
|
||||
["{"],
|
||||
["VK_HOME"],
|
||||
["VK_DOWN"],
|
||||
["VK_DOWN"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["VK_RIGHT"],
|
||||
["Ctrl+Space", {total: 1, current: 0}],
|
||||
];
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
let { panel, ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
let { cssProperties } = yield initCssProperties(panel._toolbox);
|
||||
let testCases = getTestCases(cssProperties);
|
||||
|
||||
yield ui.selectStyleSheet(ui.editors[1].styleSheet);
|
||||
let editor = yield ui.editors[1].getSourceEditor();
|
||||
|
||||
let sourceEditor = editor.sourceEditor;
|
||||
let popup = sourceEditor.getAutocompletionPopup();
|
||||
|
||||
yield SimpleTest.promiseFocus(panel.panelWindow);
|
||||
|
||||
for (let index in testCases) {
|
||||
yield testState(testCases, index, sourceEditor, popup, panel.panelWindow);
|
||||
yield checkState(testCases, index, sourceEditor, popup);
|
||||
}
|
||||
});
|
||||
|
||||
function testState(testCases, index, sourceEditor, popup, panelWindow) {
|
||||
let [key, details] = testCases[index];
|
||||
let entered;
|
||||
if (details) {
|
||||
entered = details.entered;
|
||||
}
|
||||
let mods = {};
|
||||
|
||||
info("pressing key " + key + " to get result: " +
|
||||
JSON.stringify(testCases[index]) + " for index " + index);
|
||||
|
||||
let evt = "after-suggest";
|
||||
|
||||
if (key == "Ctrl+Space") {
|
||||
key = " ";
|
||||
mods.ctrlKey = true;
|
||||
} else if (key == "VK_RETURN" && entered) {
|
||||
evt = "popup-hidden";
|
||||
} else if (/(left|right|return|home|end)/ig.test(key) ||
|
||||
(key == "VK_DOWN" && !popup.isOpen)) {
|
||||
evt = "cursorActivity";
|
||||
} else if (key == "VK_TAB" || key == "VK_UP" || key == "VK_DOWN") {
|
||||
evt = "suggestion-entered";
|
||||
}
|
||||
|
||||
let ready = sourceEditor.once(evt);
|
||||
EventUtils.synthesizeKey(key, mods, panelWindow);
|
||||
|
||||
return ready;
|
||||
}
|
||||
|
||||
function checkState(testCases, index, sourceEditor, popup) {
|
||||
let deferred = defer();
|
||||
executeSoon(() => {
|
||||
let [, details] = testCases[index];
|
||||
details = details || {};
|
||||
let {total, current, inserted} = details;
|
||||
|
||||
if (total != undefined) {
|
||||
ok(popup.isOpen, "Popup is open for index " + index);
|
||||
is(total, popup.itemCount,
|
||||
"Correct total suggestions for index " + index);
|
||||
is(current, popup.selectedIndex,
|
||||
"Correct index is selected for index " + index);
|
||||
if (inserted) {
|
||||
let { text } = popup.getItemAtIndex(current);
|
||||
let { line, ch } = sourceEditor.getCursor();
|
||||
let lineText = sourceEditor.getText(line);
|
||||
is(lineText.substring(ch - text.length, ch), text,
|
||||
"Current suggestion from the popup is inserted into the editor.");
|
||||
}
|
||||
} else {
|
||||
ok(!popup.isOpen, "Popup is closed for index " + index);
|
||||
if (inserted) {
|
||||
let { text } = popup.getItemAtIndex(current);
|
||||
let { line, ch } = sourceEditor.getCursor();
|
||||
let lineText = sourceEditor.getText(line);
|
||||
is(lineText.substring(ch - text.length, ch), text,
|
||||
"Current suggestion from the popup is inserted into the editor.");
|
||||
}
|
||||
}
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all property names and a map of property name vs possible
|
||||
* CSS values provided by the Gecko engine.
|
||||
*
|
||||
* @return {Object} An object with following properties:
|
||||
* - CSSProperties {Array} Array of string containing all the possible
|
||||
* CSS property names.
|
||||
* - CSSValues {Object|Map} A map where key is the property name and
|
||||
* value is an array of string containing all the possible
|
||||
* CSS values the property can have.
|
||||
*/
|
||||
function getCSSKeywords(cssProperties) {
|
||||
let props = {};
|
||||
let propNames = cssProperties.getNames();
|
||||
propNames.forEach(prop => {
|
||||
props[prop] = cssProperties.getValues(prop).sort();
|
||||
});
|
||||
return {
|
||||
CSSValues: props,
|
||||
CSSProperties: propNames.sort()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a function that returns the number of expected suggestions for the given
|
||||
* property and value. If the value is not null, returns the number of values starting
|
||||
* with `value`. Returns the number of properties starting with `property` otherwise.
|
||||
*/
|
||||
function suggestionNumberGetter({CSSProperties, CSSValues}) {
|
||||
return (property, value) => {
|
||||
if (value == null) {
|
||||
return CSSProperties.filter(prop => prop.startsWith(property))
|
||||
.slice(0, MAX_SUGGESTIONS).length;
|
||||
}
|
||||
return CSSValues[property].filter(val => val.startsWith(value))
|
||||
.slice(0, MAX_SUGGESTIONS).length;
|
||||
};
|
||||
}
|
||||
34
devtools/client/styleeditor/test/browser_styleeditor_bom.js
Normal file
34
devtools/client/styleeditor/test/browser_styleeditor_bom.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* 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 BOM_CSS = TEST_BASE_HTTPS + "utf-16.css";
|
||||
const DOCUMENT = "data:text/html;charset=UTF-8," +
|
||||
encodeURIComponent(
|
||||
["<!DOCTYPE html>",
|
||||
"<html>",
|
||||
" <head>",
|
||||
" <title>Bug 1301854</title>",
|
||||
' <link rel="stylesheet" type="text/css" href="' + BOM_CSS + '">',
|
||||
" </head>",
|
||||
" <body>",
|
||||
" </body>",
|
||||
"</html>"
|
||||
].join("\n"));
|
||||
|
||||
const CONTENTS = "// Note that this file must be utf-16 with a " +
|
||||
"BOM for the test to make sense.\n";
|
||||
|
||||
add_task(function* () {
|
||||
let {ui} = yield openStyleEditorForURL(DOCUMENT);
|
||||
|
||||
is(ui.editors.length, 1, "correct number of editors");
|
||||
|
||||
let editor = ui.editors[0];
|
||||
yield editor.getSourceEditor();
|
||||
|
||||
let text = editor.sourceEditor.getText();
|
||||
is(text, CONTENTS, "editor contains expected text");
|
||||
});
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that sheets inside iframes are shown in the editor.
|
||||
|
||||
add_task(function* () {
|
||||
function makeStylesheet(selector) {
|
||||
return ("data:text/css;charset=UTF-8," +
|
||||
encodeURIComponent(selector + " { }"));
|
||||
}
|
||||
|
||||
function makeDocument(stylesheets, framedDocuments) {
|
||||
stylesheets = stylesheets || [];
|
||||
framedDocuments = framedDocuments || [];
|
||||
return "data:text/html;charset=UTF-8," + encodeURIComponent(
|
||||
Array.prototype.concat.call(
|
||||
["<!DOCTYPE html>",
|
||||
"<html>",
|
||||
"<head>",
|
||||
"<title>Bug 740541</title>"],
|
||||
stylesheets.map(function (sheet) {
|
||||
return '<link rel="stylesheet" type="text/css" href="' + sheet + '">';
|
||||
}),
|
||||
["</head>",
|
||||
"<body>"],
|
||||
framedDocuments.map(function (doc) {
|
||||
return '<iframe src="' + doc + '"></iframe>';
|
||||
}),
|
||||
["</body>",
|
||||
"</html>"]
|
||||
).join("\n"));
|
||||
}
|
||||
|
||||
const DOCUMENT_WITH_INLINE_STYLE = "data:text/html;charset=UTF-8," +
|
||||
encodeURIComponent(
|
||||
["<!DOCTYPE html>",
|
||||
"<html>",
|
||||
" <head>",
|
||||
" <title>Bug 740541</title>",
|
||||
' <style type="text/css">',
|
||||
" .something {",
|
||||
" }",
|
||||
" </style>",
|
||||
" </head>",
|
||||
" <body>",
|
||||
" </body>",
|
||||
" </html>"
|
||||
].join("\n"));
|
||||
|
||||
const FOUR = TEST_BASE_HTTP + "four.html";
|
||||
|
||||
const SIMPLE = TEST_BASE_HTTP + "simple.css";
|
||||
|
||||
const SIMPLE_DOCUMENT = TEST_BASE_HTTP + "simple.html";
|
||||
|
||||
const TESTCASE_URI = makeDocument(
|
||||
[makeStylesheet(".a")],
|
||||
[makeDocument([],
|
||||
[FOUR,
|
||||
DOCUMENT_WITH_INLINE_STYLE]),
|
||||
makeDocument([makeStylesheet(".b"),
|
||||
SIMPLE],
|
||||
[makeDocument([makeStylesheet(".c")],
|
||||
[])]),
|
||||
makeDocument([SIMPLE], []),
|
||||
SIMPLE_DOCUMENT
|
||||
]);
|
||||
|
||||
const EXPECTED_STYLE_SHEET_COUNT = 12;
|
||||
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
is(ui.editors.length, EXPECTED_STYLE_SHEET_COUNT,
|
||||
"Got the expected number of style sheets.");
|
||||
});
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that middle click on style sheet doesn't open styleeditor.xul in a new
|
||||
// tab (bug 851132).
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "four.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", onTabAdded, false);
|
||||
|
||||
yield ui.editors[0].getSourceEditor();
|
||||
info("first editor selected");
|
||||
|
||||
info("Left-clicking on the second editor link.");
|
||||
yield clickOnStyleSheetLink(ui.editors[1], 0);
|
||||
|
||||
info("Waiting for the second editor to be selected.");
|
||||
let editor = yield ui.once("editor-selected");
|
||||
|
||||
ok(editor.sourceEditor.hasFocus(),
|
||||
"Left mouse click gave second editor focus.");
|
||||
|
||||
// middle mouse click should not open a new tab
|
||||
info("Middle clicking on the third editor link.");
|
||||
yield clickOnStyleSheetLink(ui.editors[2], 1);
|
||||
});
|
||||
|
||||
/**
|
||||
* A helper that clicks on style sheet link in the sidebar.
|
||||
*
|
||||
* @param {StyleSheetEditor} editor
|
||||
* The editor of which link should be clicked.
|
||||
* @param {MouseEvent.button} button
|
||||
* The button to click the link with.
|
||||
*/
|
||||
function* clickOnStyleSheetLink(editor, button) {
|
||||
let window = editor._window;
|
||||
let link = editor.summary.querySelector(".stylesheet-name");
|
||||
|
||||
info("Waiting for focus.");
|
||||
yield SimpleTest.promiseFocus(window);
|
||||
|
||||
info("Pressing button " + button + " on style sheet name link.");
|
||||
EventUtils.synthesizeMouseAtCenter(link, { button }, window);
|
||||
}
|
||||
|
||||
function onTabAdded() {
|
||||
ok(false, "middle mouse click has opened a new tab");
|
||||
}
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", onTabAdded, false);
|
||||
});
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const SIMPLE = TEST_BASE_HTTP + "simple.css";
|
||||
const DOCUMENT_WITH_ONE_STYLESHEET = "data:text/html;charset=UTF-8," +
|
||||
encodeURIComponent(
|
||||
["<!DOCTYPE html>",
|
||||
"<html>",
|
||||
" <head>",
|
||||
" <title>Bug 870339</title>",
|
||||
' <link rel="stylesheet" type="text/css" href="' + SIMPLE + '">',
|
||||
" </head>",
|
||||
" <body>",
|
||||
" </body>",
|
||||
"</html>"
|
||||
].join("\n"));
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(DOCUMENT_WITH_ONE_STYLESHEET);
|
||||
|
||||
// Spam the _onNewDocument callback multiple times before the
|
||||
// StyleEditorActor has a chance to respond to the first one.
|
||||
const SPAM_COUNT = 2;
|
||||
for (let i = 0; i < SPAM_COUNT; ++i) {
|
||||
ui._onNewDocument();
|
||||
}
|
||||
|
||||
// Wait for the StyleEditorActor to respond to each "newDocument"
|
||||
// message.
|
||||
yield new Promise(resolve => {
|
||||
let loadCount = 0;
|
||||
ui.on("stylesheets-reset", function onReset() {
|
||||
++loadCount;
|
||||
if (loadCount == SPAM_COUNT) {
|
||||
ui.off("stylesheets-reset", onReset);
|
||||
// No matter how large SPAM_COUNT is, the number of style
|
||||
// sheets should never be more than the number of style sheets
|
||||
// in the document.
|
||||
is(ui.editors.length, 1, "correct style sheet count");
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Resources</title>
|
||||
<script type="text/javascript;version=1.8" id="script1">
|
||||
"use strict";
|
||||
|
||||
window.addEventListener("load", function onload() {
|
||||
let pid = document.getElementById("pid");
|
||||
let div = document.createElement("div");
|
||||
div.id = "divid";
|
||||
div.classList.add("divclass");
|
||||
div.appendChild(document.createTextNode("div"));
|
||||
div.setAttribute("data-a1", "div");
|
||||
pid.parentNode.appendChild(div);
|
||||
});
|
||||
</script>
|
||||
<script src="resources_inpage.jsi"></script>
|
||||
<link rel="stylesheet" type="text/css" href="resources_inpage1.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="resources_inpage2.css"/>
|
||||
<style type="text/css">
|
||||
p { color: #800; }
|
||||
div { color: #008; }
|
||||
h4 { color: #080; }
|
||||
h3 { color: #880; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<style type="text/css" id=style2>
|
||||
.pclass { background-color: #FEE; }
|
||||
.divclass { background-color: #EEF; }
|
||||
.h4class { background-color: #EFE; }
|
||||
.h3class { background-color: #FFE; }
|
||||
</style>
|
||||
|
||||
<p class="pclass" id="pid" data-a1="p">paragraph</p>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
let pid = document.getElementById("pid");
|
||||
let h4 = document.createElement("h4");
|
||||
h4.id = "h4id";
|
||||
h4.classList.add("h4class");
|
||||
h4.appendChild(document.createTextNode("h4"));
|
||||
h4.setAttribute("data-a1", "h4");
|
||||
pid.parentNode.appendChild(h4);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
215
devtools/client/styleeditor/test/browser_styleeditor_cmd_edit.js
Normal file
215
devtools/client/styleeditor/test/browser_styleeditor_cmd_edit.js
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests that the edit command works
|
||||
|
||||
// Import the GCLI test helper
|
||||
/* import-globals-from ../../commandline/test/helpers.js */
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/commandline/test/helpers.js",
|
||||
this);
|
||||
|
||||
const TEST_URI = "http://example.com/browser/devtools/client/styleeditor/" +
|
||||
"test/browser_styleeditor_cmd_edit.html";
|
||||
|
||||
add_task(function* () {
|
||||
let options = yield helpers.openTab(TEST_URI);
|
||||
yield helpers.openToolbar(options);
|
||||
|
||||
yield helpers.audit(options, [
|
||||
{
|
||||
setup: "edit",
|
||||
check: {
|
||||
input: "edit",
|
||||
hints: " <resource> [line]",
|
||||
markup: "VVVV",
|
||||
status: "ERROR",
|
||||
args: {
|
||||
resource: { status: "INCOMPLETE" },
|
||||
line: { status: "VALID" },
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: "edit i",
|
||||
check: {
|
||||
input: "edit i",
|
||||
hints: "nline-css [line]",
|
||||
markup: "VVVVVI",
|
||||
status: "ERROR",
|
||||
args: {
|
||||
resource: { arg: " i", status: "INCOMPLETE" },
|
||||
line: { status: "VALID" },
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: "edit c",
|
||||
check: {
|
||||
input: "edit c",
|
||||
hints: "ss#style2 [line]",
|
||||
markup: "VVVVVI",
|
||||
status: "ERROR",
|
||||
args: {
|
||||
resource: { arg: " c", status: "INCOMPLETE" },
|
||||
line: { status: "VALID" },
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: "edit http",
|
||||
check: {
|
||||
input: "edit http",
|
||||
hints: "://example.com/browser/devtools/client/styleeditor/test/" +
|
||||
"resources_inpage1.css [line]",
|
||||
markup: "VVVVVIIII",
|
||||
status: "ERROR",
|
||||
args: {
|
||||
resource: {
|
||||
arg: " http",
|
||||
status: "INCOMPLETE",
|
||||
message: "Value required for \u2018resource\u2019."
|
||||
},
|
||||
line: { status: "VALID" },
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: "edit page1",
|
||||
check: {
|
||||
input: "edit page1",
|
||||
hints: " [line] -> http://example.com/browser/devtools/client/" +
|
||||
"styleeditor/test/resources_inpage1.css",
|
||||
markup: "VVVVVIIIII",
|
||||
status: "ERROR",
|
||||
args: {
|
||||
resource: {
|
||||
arg: " page1",
|
||||
status: "INCOMPLETE",
|
||||
message: "Value required for \u2018resource\u2019."
|
||||
},
|
||||
line: { status: "VALID" },
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: "edit page2",
|
||||
check: {
|
||||
input: "edit page2",
|
||||
hints: " [line] -> http://example.com/browser/devtools/client/" +
|
||||
"styleeditor/test/resources_inpage2.css",
|
||||
markup: "VVVVVIIIII",
|
||||
status: "ERROR",
|
||||
args: {
|
||||
resource: {
|
||||
arg: " page2",
|
||||
status: "INCOMPLETE",
|
||||
message: "Value required for \u2018resource\u2019."
|
||||
},
|
||||
line: { status: "VALID" },
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: "edit stylez",
|
||||
check: {
|
||||
input: "edit stylez",
|
||||
hints: " [line]",
|
||||
markup: "VVVVVEEEEEE",
|
||||
status: "ERROR",
|
||||
args: {
|
||||
resource: {
|
||||
arg: " stylez",
|
||||
status: "ERROR", message: "Can\u2019t use \u2018stylez\u2019." },
|
||||
line: { status: "VALID" },
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: "edit css#style2",
|
||||
check: {
|
||||
input: "edit css#style2",
|
||||
hints: " [line]",
|
||||
markup: "VVVVVVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
args: {
|
||||
resource: { arg: " css#style2", status: "VALID", message: "" },
|
||||
line: { status: "VALID" },
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: "edit css#style2 5",
|
||||
check: {
|
||||
input: "edit css#style2 5",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
args: {
|
||||
resource: { arg: " css#style2", status: "VALID", message: "" },
|
||||
line: { value: 5, arg: " 5", status: "VALID" },
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: "edit css#style2 0",
|
||||
check: {
|
||||
input: "edit css#style2 0",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVVVVVVVVE",
|
||||
status: "ERROR",
|
||||
args: {
|
||||
resource: { arg: " css#style2", status: "VALID", message: "" },
|
||||
line: {
|
||||
arg: " 0",
|
||||
status: "ERROR",
|
||||
message: "0 is smaller than minimum allowed: 1."
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: "edit css#style2 -1",
|
||||
check: {
|
||||
input: "edit css#style2 -1",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVVVVVVVVEE",
|
||||
status: "ERROR",
|
||||
args: {
|
||||
resource: { arg: " css#style2", status: "VALID", message: "" },
|
||||
line: {
|
||||
arg: " -1",
|
||||
status: "ERROR",
|
||||
message: "-1 is smaller than minimum allowed: 1."
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
]);
|
||||
|
||||
let toolbox = gDevTools.getToolbox(options.target);
|
||||
ok(toolbox == null, "toolbox is closed");
|
||||
|
||||
yield helpers.audit(options, [
|
||||
{
|
||||
setup: "edit css#style2",
|
||||
check: {
|
||||
input: "edit css#style2",
|
||||
},
|
||||
exec: { output: "" }
|
||||
},
|
||||
]);
|
||||
|
||||
toolbox = gDevTools.getToolbox(options.target);
|
||||
ok(toolbox != null, "toolbox is open");
|
||||
|
||||
let styleEditor = toolbox.getCurrentPanel();
|
||||
ok(typeof styleEditor.selectStyleSheet === "function", "styleeditor is open");
|
||||
|
||||
yield toolbox.destroy();
|
||||
|
||||
yield helpers.closeToolbar(options);
|
||||
yield helpers.closeTab(options);
|
||||
});
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/* 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";
|
||||
|
||||
// Test that style sheets can be disabled and enabled.
|
||||
|
||||
// https rather than chrome to improve coverage
|
||||
const TESTCASE_URI = TEST_BASE_HTTPS + "simple.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { panel, ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
let editor = yield ui.editors[0].getSourceEditor();
|
||||
|
||||
let summary = editor.summary;
|
||||
let enabledToggle = summary.querySelector(".stylesheet-enabled");
|
||||
ok(enabledToggle, "enabled toggle button exists");
|
||||
|
||||
is(editor.styleSheet.disabled, false,
|
||||
"first stylesheet is initially enabled");
|
||||
|
||||
is(summary.classList.contains("disabled"), false,
|
||||
"first stylesheet is initially enabled, UI does not have DISABLED class");
|
||||
|
||||
info("Disabling the first stylesheet.");
|
||||
yield toggleEnabled(editor, enabledToggle, panel.panelWindow);
|
||||
|
||||
is(editor.styleSheet.disabled, true, "first stylesheet is now disabled");
|
||||
is(summary.classList.contains("disabled"), true,
|
||||
"first stylesheet is now disabled, UI has DISABLED class");
|
||||
|
||||
info("Enabling the first stylesheet again.");
|
||||
yield toggleEnabled(editor, enabledToggle, panel.panelWindow);
|
||||
|
||||
is(editor.styleSheet.disabled, false,
|
||||
"first stylesheet is now enabled again");
|
||||
is(summary.classList.contains("disabled"), false,
|
||||
"first stylesheet is now enabled again, UI does not have DISABLED class");
|
||||
});
|
||||
|
||||
function* toggleEnabled(editor, enabledToggle, panelWindow) {
|
||||
let changed = editor.once("property-change");
|
||||
|
||||
info("Waiting for focus.");
|
||||
yield SimpleTest.promiseFocus(panelWindow);
|
||||
|
||||
info("Clicking on the toggle.");
|
||||
EventUtils.synthesizeMouseAtCenter(enabledToggle, {}, panelWindow);
|
||||
|
||||
info("Waiting for stylesheet to be disabled.");
|
||||
let property = yield changed;
|
||||
while (property !== "disabled") {
|
||||
info("Ignoring property-change for '" + property + "'.");
|
||||
property = yield editor.once("property-change");
|
||||
}
|
||||
}
|
||||
|
|
@ -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/ */
|
||||
"use strict";
|
||||
|
||||
// A test to ensure Style Editor doesn't bybass cache when loading style sheet
|
||||
// contents (bug 978688).
|
||||
|
||||
const TEST_URL = TEST_BASE_HTTP + "doc_uncached.html";
|
||||
|
||||
add_task(function* () {
|
||||
info("Opening netmonitor");
|
||||
let tab = yield addTab("about:blank");
|
||||
let target = TargetFactory.forTab(tab);
|
||||
let toolbox = yield gDevTools.showToolbox(target, "netmonitor");
|
||||
let netmonitor = toolbox.getPanel("netmonitor");
|
||||
netmonitor._view.RequestsMenu.lazyUpdate = false;
|
||||
|
||||
info("Navigating to test page");
|
||||
yield navigateTo(TEST_URL);
|
||||
|
||||
info("Opening Style Editor");
|
||||
let styleeditor = yield toolbox.selectTool("styleeditor");
|
||||
|
||||
info("Waiting for the source to be loaded.");
|
||||
yield styleeditor.UI.editors[0].getSourceEditor();
|
||||
|
||||
info("Checking Netmonitor contents.");
|
||||
let attachments = [];
|
||||
for (let item of netmonitor._view.RequestsMenu) {
|
||||
if (item.attachment.url.endsWith("doc_uncached.css")) {
|
||||
attachments.push(item.attachment);
|
||||
}
|
||||
}
|
||||
|
||||
is(attachments.length, 2,
|
||||
"Got two requests for doc_uncached.css after Style Editor was loaded.");
|
||||
ok(attachments[1].fromCache,
|
||||
"Second request was loaded from browser cache");
|
||||
});
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/* 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";
|
||||
|
||||
// Test that 'Save' function works.
|
||||
|
||||
const TESTCASE_URI_HTML = TEST_BASE_HTTP + "simple.html";
|
||||
const TESTCASE_URI_CSS = TEST_BASE_HTTP + "simple.css";
|
||||
|
||||
var tempScope = {};
|
||||
Components.utils.import("resource://gre/modules/FileUtils.jsm", tempScope);
|
||||
Components.utils.import("resource://gre/modules/NetUtil.jsm", tempScope);
|
||||
var FileUtils = tempScope.FileUtils;
|
||||
var NetUtil = tempScope.NetUtil;
|
||||
|
||||
add_task(function* () {
|
||||
let htmlFile = yield copy(TESTCASE_URI_HTML, "simple.html");
|
||||
yield copy(TESTCASE_URI_CSS, "simple.css");
|
||||
let uri = Services.io.newFileURI(htmlFile);
|
||||
let filePath = uri.resolve("");
|
||||
|
||||
let { ui } = yield openStyleEditorForURL(filePath);
|
||||
|
||||
let editor = ui.editors[0];
|
||||
yield editor.getSourceEditor();
|
||||
|
||||
info("Editing the style sheet.");
|
||||
let dirty = editor.sourceEditor.once("dirty-change");
|
||||
let beginCursor = {line: 0, ch: 0};
|
||||
editor.sourceEditor.replaceText("DIRTY TEXT", beginCursor, beginCursor);
|
||||
|
||||
yield dirty;
|
||||
|
||||
is(editor.sourceEditor.isClean(), false, "Editor is dirty.");
|
||||
ok(editor.summary.classList.contains("unsaved"),
|
||||
"Star icon is present in the corresponding summary.");
|
||||
|
||||
info("Saving the changes.");
|
||||
dirty = editor.sourceEditor.once("dirty-change");
|
||||
|
||||
editor.saveToFile(null, function (file) {
|
||||
ok(file, "file should get saved directly when using a file:// URI");
|
||||
});
|
||||
|
||||
yield dirty;
|
||||
|
||||
is(editor.sourceEditor.isClean(), true, "Editor is clean.");
|
||||
ok(!editor.summary.classList.contains("unsaved"),
|
||||
"Star icon is not present in the corresponding summary.");
|
||||
});
|
||||
|
||||
function copy(srcChromeURL, destFileName) {
|
||||
let deferred = defer();
|
||||
let destFile = FileUtils.getFile("ProfD", [destFileName]);
|
||||
write(read(srcChromeURL), destFile, deferred.resolve);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function read(srcChromeURL) {
|
||||
let scriptableStream = Cc["@mozilla.org/scriptableinputstream;1"]
|
||||
.getService(Ci.nsIScriptableInputStream);
|
||||
|
||||
let channel = NetUtil.newChannel({
|
||||
uri: srcChromeURL,
|
||||
loadUsingSystemPrincipal: true
|
||||
});
|
||||
let input = channel.open2();
|
||||
scriptableStream.init(input);
|
||||
|
||||
let data = "";
|
||||
while (input.available()) {
|
||||
data = data.concat(scriptableStream.read(input.available()));
|
||||
}
|
||||
scriptableStream.close();
|
||||
input.close();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function write(data, file, callback) {
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
|
||||
converter.charset = "UTF-8";
|
||||
|
||||
let istream = converter.convertToInputStream(data);
|
||||
let ostream = FileUtils.openSafeFileOutputStream(file);
|
||||
|
||||
NetUtil.asyncCopy(istream, ostream, function (status) {
|
||||
if (!Components.isSuccessCode(status)) {
|
||||
info("Couldn't write to " + file.path);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(file);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/* 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";
|
||||
|
||||
// Test that hovering over a simple selector in the style-editor requests the
|
||||
// highlighting of the corresponding nodes
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf8," +
|
||||
"<style>div{color:red}</style><div>highlighter test</div>";
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(TEST_URL);
|
||||
let editor = ui.editors[0];
|
||||
|
||||
// Mock the highlighter so we can locally assert that things happened
|
||||
// correctly instead of accessing the highlighter elements
|
||||
editor.highlighter = {
|
||||
isShown: false,
|
||||
options: null,
|
||||
|
||||
show: function (node, options) {
|
||||
this.isShown = true;
|
||||
this.options = options;
|
||||
return promise.resolve();
|
||||
},
|
||||
|
||||
hide: function () {
|
||||
this.isShown = false;
|
||||
}
|
||||
};
|
||||
|
||||
info("Expecting a node-highlighted event");
|
||||
let onHighlighted = editor.once("node-highlighted");
|
||||
|
||||
info("Simulate a mousemove event on the div selector");
|
||||
editor._onMouseMove({clientX: 56, clientY: 10});
|
||||
yield onHighlighted;
|
||||
|
||||
ok(editor.highlighter.isShown, "The highlighter is now shown");
|
||||
is(editor.highlighter.options.selector, "div", "The selector is correct");
|
||||
|
||||
info("Simulate a mousemove event elsewhere in the editor");
|
||||
editor._onMouseMove({clientX: 16, clientY: 0});
|
||||
|
||||
ok(!editor.highlighter.isShown, "The highlighter is now hidden");
|
||||
});
|
||||
|
|
@ -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/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the import button in the UI works.
|
||||
|
||||
// http rather than chrome to improve coverage
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
|
||||
|
||||
var tempScope = {};
|
||||
Components.utils.import("resource://gre/modules/FileUtils.jsm", tempScope);
|
||||
var FileUtils = tempScope.FileUtils;
|
||||
|
||||
const FILENAME = "styleeditor-import-test.css";
|
||||
const SOURCE = "body{background:red;}";
|
||||
|
||||
add_task(function* () {
|
||||
let { panel, ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
let added = ui.once("editor-added");
|
||||
importSheet(ui, panel.panelWindow);
|
||||
|
||||
info("Waiting for editor to be added for the imported sheet.");
|
||||
let editor = yield added;
|
||||
|
||||
is(editor.savedFile.leafName, FILENAME,
|
||||
"imported stylesheet will be saved directly into the same file");
|
||||
is(editor.friendlyName, FILENAME,
|
||||
"imported stylesheet has the same name as the filename");
|
||||
});
|
||||
|
||||
function importSheet(ui, panelWindow) {
|
||||
// create file to import first
|
||||
let file = FileUtils.getFile("ProfD", [FILENAME]);
|
||||
let ostream = FileUtils.openSafeFileOutputStream(file);
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
let istream = converter.convertToInputStream(SOURCE);
|
||||
NetUtil.asyncCopy(istream, ostream, function () {
|
||||
FileUtils.closeSafeFileOutputStream(ostream);
|
||||
|
||||
// click the import button now that the file to import is ready
|
||||
ui._mockImportFile = file;
|
||||
|
||||
waitForFocus(function () {
|
||||
let document = panelWindow.document;
|
||||
let importButton = document.querySelector(".style-editor-importButton");
|
||||
ok(importButton, "import button exists");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(importButton, {}, panelWindow);
|
||||
}, panelWindow);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/* 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";
|
||||
|
||||
// Test that style editor shows sheets loaded with @import rules.
|
||||
|
||||
// http rather than chrome to improve coverage
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "import.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
is(ui.editors.length, 3,
|
||||
"there are 3 stylesheets after loading @imports");
|
||||
|
||||
is(ui.editors[0].styleSheet.href, TEST_BASE_HTTP + "simple.css",
|
||||
"stylesheet 1 is simple.css");
|
||||
|
||||
is(ui.editors[1].styleSheet.href, TEST_BASE_HTTP + "import.css",
|
||||
"stylesheet 2 is import.css");
|
||||
|
||||
is(ui.editors[2].styleSheet.href, TEST_BASE_HTTP + "import2.css",
|
||||
"stylesheet 3 is import2.css");
|
||||
});
|
||||
45
devtools/client/styleeditor/test/browser_styleeditor_init.js
Normal file
45
devtools/client/styleeditor/test/browser_styleeditor_init.js
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
"use strict";
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Checks that style editor contains correct stylesheets after initialization.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
|
||||
const EXPECTED_SHEETS = [
|
||||
{
|
||||
sheetIndex: 0,
|
||||
name: /^simple.css$/,
|
||||
rules: 1,
|
||||
active: true
|
||||
}, {
|
||||
sheetIndex: 1,
|
||||
name: /^<.*>$/,
|
||||
rules: 3,
|
||||
active: false
|
||||
}
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
is(ui.editors.length, 2, "The UI contains two style sheets.");
|
||||
checkSheet(ui.editors[0], EXPECTED_SHEETS[0]);
|
||||
checkSheet(ui.editors[1], EXPECTED_SHEETS[1]);
|
||||
});
|
||||
|
||||
function checkSheet(editor, expected) {
|
||||
is(editor.styleSheet.styleSheetIndex, expected.sheetIndex,
|
||||
"Style sheet has correct index.");
|
||||
|
||||
let summary = editor.summary;
|
||||
let name = summary.querySelector(".stylesheet-name > label")
|
||||
.getAttribute("value");
|
||||
ok(expected.name.test(name), "The name '" + name + "' is correct.");
|
||||
|
||||
let ruleCount = summary.querySelector(".stylesheet-rule-count").textContent;
|
||||
is(parseInt(ruleCount, 10), expected.rules, "the rule count is correct");
|
||||
|
||||
is(summary.classList.contains("splitview-active"), expected.active,
|
||||
"The active status for this sheet is correct.");
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/* 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";
|
||||
|
||||
// Test that inline style sheets get correct names if they are saved to disk and
|
||||
// that those names survice a reload but not navigation to another page.
|
||||
|
||||
const FIRST_TEST_PAGE = TEST_BASE_HTTP + "inline-1.html";
|
||||
const SECOND_TEST_PAGE = TEST_BASE_HTTP + "inline-2.html";
|
||||
const SAVE_PATH = "test.css";
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(FIRST_TEST_PAGE);
|
||||
|
||||
testIndentifierGeneration(ui);
|
||||
|
||||
yield saveFirstInlineStyleSheet(ui);
|
||||
yield testFriendlyNamesAfterSave(ui);
|
||||
yield reloadPageAndWaitForStyleSheets(ui);
|
||||
yield testFriendlyNamesAfterSave(ui);
|
||||
yield navigateToAndWaitForStyleSheets(SECOND_TEST_PAGE, ui);
|
||||
yield testFriendlyNamesAfterNavigation(ui);
|
||||
});
|
||||
|
||||
function testIndentifierGeneration(ui) {
|
||||
let fakeStyleSheetFile = {
|
||||
"href": "http://example.com/test.css",
|
||||
"nodeHref": "http://example.com/",
|
||||
"styleSheetIndex": 1
|
||||
};
|
||||
|
||||
let fakeInlineStyleSheet = {
|
||||
"href": null,
|
||||
"nodeHref": "http://example.com/",
|
||||
"styleSheetIndex": 2
|
||||
};
|
||||
|
||||
is(ui.getStyleSheetIdentifier(fakeStyleSheetFile),
|
||||
"http://example.com/test.css",
|
||||
"URI is the identifier of style sheet file.");
|
||||
|
||||
is(ui.getStyleSheetIdentifier(fakeInlineStyleSheet),
|
||||
"inline-2-at-http://example.com/",
|
||||
"Inline sheets are identified by their page and position in the page.");
|
||||
}
|
||||
|
||||
function saveFirstInlineStyleSheet(ui) {
|
||||
let deferred = defer();
|
||||
let editor = ui.editors[0];
|
||||
|
||||
let destFile = FileUtils.getFile("ProfD", [SAVE_PATH]);
|
||||
|
||||
editor.saveToFile(destFile, function (file) {
|
||||
ok(file, "File was correctly saved.");
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testFriendlyNamesAfterSave(ui) {
|
||||
let firstEditor = ui.editors[0];
|
||||
let secondEditor = ui.editors[1];
|
||||
|
||||
// The friendly name of first sheet should've been remembered, the second
|
||||
// should not be the same (bug 969900).
|
||||
is(firstEditor.friendlyName, SAVE_PATH,
|
||||
"Friendly name is correct for the saved inline style sheet.");
|
||||
isnot(secondEditor.friendlyName, SAVE_PATH,
|
||||
"Friendly name for the second inline sheet isn't the same as the first.");
|
||||
|
||||
return promise.resolve(null);
|
||||
}
|
||||
|
||||
function testFriendlyNamesAfterNavigation(ui) {
|
||||
let firstEditor = ui.editors[0];
|
||||
let secondEditor = ui.editors[1];
|
||||
|
||||
// Inline style sheets shouldn't have the name of previously saved file as the
|
||||
// page is different.
|
||||
isnot(firstEditor.friendlyName, SAVE_PATH,
|
||||
"The first editor doesn't have the save path as a friendly name.");
|
||||
isnot(secondEditor.friendlyName, SAVE_PATH,
|
||||
"The second editor doesn't have the save path as a friendly name.");
|
||||
|
||||
return promise.resolve(null);
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/* 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";
|
||||
|
||||
// Test that style editor loads correctly.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "longload.html";
|
||||
|
||||
add_task(function* () {
|
||||
// launch Style Editor right when the tab is created (before load)
|
||||
// this checks that the Style Editor still launches correctly when it is
|
||||
// opened *while* the page is still loading. The Style Editor should not
|
||||
// signal that it is loaded until the accompanying content page is loaded.
|
||||
let tabAdded = addTab(TESTCASE_URI);
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
let styleEditorLoaded = gDevTools.showToolbox(target, "styleeditor");
|
||||
|
||||
yield Promise.all([tabAdded, styleEditorLoaded]);
|
||||
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
let panel = toolbox.getPanel("styleeditor");
|
||||
let { panelWindow } = panel;
|
||||
|
||||
let root = panelWindow.document.querySelector(".splitview-root");
|
||||
ok(!root.classList.contains("loading"),
|
||||
"style editor root element does not have 'loading' class name anymore");
|
||||
|
||||
let button = panelWindow.document.querySelector(".style-editor-newButton");
|
||||
ok(!button.hasAttribute("disabled"),
|
||||
"new style sheet button is enabled");
|
||||
|
||||
button = panelWindow.document.querySelector(".style-editor-importButton");
|
||||
ok(!button.hasAttribute("disabled"),
|
||||
"import button is enabled");
|
||||
});
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/* 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";
|
||||
|
||||
// Test that the stylesheets can be loaded correctly with containers
|
||||
// (bug 1282660).
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
|
||||
const EXPECTED_SHEETS = [
|
||||
{
|
||||
sheetIndex: 0,
|
||||
name: /^simple.css$/,
|
||||
rules: 1,
|
||||
active: true
|
||||
}, {
|
||||
sheetIndex: 1,
|
||||
name: /^<.*>$/,
|
||||
rules: 3,
|
||||
active: false
|
||||
}
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
// Using the personal container.
|
||||
let userContextId = 1;
|
||||
let { tab } = yield* openTabInUserContext(TESTCASE_URI, userContextId);
|
||||
let { ui } = yield openStyleEditor(tab);
|
||||
|
||||
is(ui.editors.length, 2, "The UI contains two style sheets.");
|
||||
checkSheet(ui.editors[0], EXPECTED_SHEETS[0]);
|
||||
checkSheet(ui.editors[1], EXPECTED_SHEETS[1]);
|
||||
});
|
||||
|
||||
function* openTabInUserContext(uri, userContextId) {
|
||||
// Open the tab in the correct userContextId.
|
||||
let tab = gBrowser.addTab(uri, {userContextId});
|
||||
|
||||
// Select tab and make sure its browser is focused.
|
||||
gBrowser.selectedTab = tab;
|
||||
tab.ownerDocument.defaultView.focus();
|
||||
|
||||
let browser = gBrowser.getBrowserForTab(tab);
|
||||
yield BrowserTestUtils.browserLoaded(browser);
|
||||
return {tab, browser};
|
||||
}
|
||||
|
||||
function checkSheet(editor, expected) {
|
||||
is(editor.styleSheet.styleSheetIndex, expected.sheetIndex,
|
||||
"Style sheet has correct index.");
|
||||
|
||||
let summary = editor.summary;
|
||||
let name = summary.querySelector(".stylesheet-name > label")
|
||||
.getAttribute("value");
|
||||
ok(expected.name.test(name), "The name '" + name + "' is correct.");
|
||||
|
||||
let ruleCount = summary.querySelector(".stylesheet-rule-count").textContent;
|
||||
is(parseInt(ruleCount, 10), expected.rules, "the rule count is correct");
|
||||
|
||||
is(summary.classList.contains("splitview-active"), expected.active,
|
||||
"The active status for this sheet is correct.");
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
/* 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";
|
||||
|
||||
// https rather than chrome to improve coverage
|
||||
const TESTCASE_URI = TEST_BASE_HTTPS + "media-rules.html";
|
||||
const MEDIA_PREF = "devtools.styleeditor.showMediaSidebar";
|
||||
|
||||
const RESIZE = 300;
|
||||
const LABELS = ["not all", "all", "(max-width: 400px)",
|
||||
"(min-height: 300px) and (max-height: 320px)",
|
||||
"(max-width: 600px)"];
|
||||
const LINE_NOS = [1, 7, 19, 25, 31];
|
||||
const NEW_RULE = "\n@media (max-width: 600px) { div { color: blue; } }";
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
is(ui.editors.length, 2, "correct number of editors");
|
||||
|
||||
// Test first plain css editor
|
||||
let plainEditor = ui.editors[0];
|
||||
yield openEditor(plainEditor);
|
||||
testPlainEditor(plainEditor);
|
||||
|
||||
// Test editor with @media rules
|
||||
let mediaEditor = ui.editors[1];
|
||||
yield openEditor(mediaEditor);
|
||||
testMediaEditor(mediaEditor);
|
||||
|
||||
// Test that sidebar hides when flipping pref
|
||||
yield testShowHide(ui, mediaEditor);
|
||||
|
||||
// Test adding a rule updates the list
|
||||
yield testMediaRuleAdded(ui, mediaEditor);
|
||||
|
||||
// Test resizing and seeing @media matching state change
|
||||
let originalWidth = window.outerWidth;
|
||||
let originalHeight = window.outerHeight;
|
||||
|
||||
let onMatchesChange = listenForMediaChange(ui);
|
||||
window.resizeTo(RESIZE, RESIZE);
|
||||
yield onMatchesChange;
|
||||
|
||||
testMediaMatchChanged(mediaEditor);
|
||||
|
||||
window.resizeTo(originalWidth, originalHeight);
|
||||
});
|
||||
|
||||
function testPlainEditor(editor) {
|
||||
let sidebar = editor.details.querySelector(".stylesheet-sidebar");
|
||||
is(sidebar.hidden, true, "sidebar is hidden on editor without @media");
|
||||
}
|
||||
|
||||
function testMediaEditor(editor) {
|
||||
let sidebar = editor.details.querySelector(".stylesheet-sidebar");
|
||||
is(sidebar.hidden, false, "sidebar is showing on editor with @media");
|
||||
|
||||
let entries = [...sidebar.querySelectorAll(".media-rule-label")];
|
||||
is(entries.length, 4, "four @media rules displayed in sidebar");
|
||||
|
||||
testRule(entries[0], LABELS[0], false, LINE_NOS[0]);
|
||||
testRule(entries[1], LABELS[1], true, LINE_NOS[1]);
|
||||
testRule(entries[2], LABELS[2], false, LINE_NOS[2]);
|
||||
testRule(entries[3], LABELS[3], false, LINE_NOS[3]);
|
||||
}
|
||||
|
||||
function testMediaMatchChanged(editor) {
|
||||
let sidebar = editor.details.querySelector(".stylesheet-sidebar");
|
||||
|
||||
let cond = sidebar.querySelectorAll(".media-rule-condition")[2];
|
||||
is(cond.textContent, "(max-width: 400px)",
|
||||
"third rule condition text is correct");
|
||||
ok(!cond.classList.contains("media-condition-unmatched"),
|
||||
"media rule is now matched after resizing");
|
||||
}
|
||||
|
||||
function* testShowHide(UI, editor) {
|
||||
let sidebarChange = listenForMediaChange(UI);
|
||||
Services.prefs.setBoolPref(MEDIA_PREF, false);
|
||||
yield sidebarChange;
|
||||
|
||||
let sidebar = editor.details.querySelector(".stylesheet-sidebar");
|
||||
is(sidebar.hidden, true, "sidebar is hidden after flipping pref");
|
||||
|
||||
sidebarChange = listenForMediaChange(UI);
|
||||
Services.prefs.clearUserPref(MEDIA_PREF);
|
||||
yield sidebarChange;
|
||||
|
||||
is(sidebar.hidden, false, "sidebar is showing after flipping pref back");
|
||||
}
|
||||
|
||||
function* testMediaRuleAdded(UI, editor) {
|
||||
yield editor.getSourceEditor();
|
||||
let text = editor.sourceEditor.getText();
|
||||
text += NEW_RULE;
|
||||
|
||||
let listChange = listenForMediaChange(UI);
|
||||
editor.sourceEditor.setText(text);
|
||||
yield listChange;
|
||||
|
||||
let sidebar = editor.details.querySelector(".stylesheet-sidebar");
|
||||
let entries = [...sidebar.querySelectorAll(".media-rule-label")];
|
||||
is(entries.length, 5, "five @media rules after changing text");
|
||||
|
||||
testRule(entries[4], LABELS[4], false, LINE_NOS[4]);
|
||||
}
|
||||
|
||||
function testRule(rule, text, matches, lineno) {
|
||||
let cond = rule.querySelector(".media-rule-condition");
|
||||
is(cond.textContent, text, "media label is correct for " + text);
|
||||
|
||||
let matched = !cond.classList.contains("media-condition-unmatched");
|
||||
ok(matches ? matched : !matched,
|
||||
"media rule is " + (matches ? "matched" : "unmatched"));
|
||||
|
||||
let line = rule.querySelector(".media-rule-line");
|
||||
is(line.textContent, ":" + lineno, "correct line number shown");
|
||||
}
|
||||
|
||||
/* Helpers */
|
||||
|
||||
function openEditor(editor) {
|
||||
getLinkFor(editor).click();
|
||||
|
||||
return editor.getSourceEditor();
|
||||
}
|
||||
|
||||
function listenForMediaChange(UI) {
|
||||
let deferred = defer();
|
||||
UI.once("media-list-changed", () => {
|
||||
deferred.resolve();
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function getLinkFor(editor) {
|
||||
return editor.summary.querySelector(".stylesheet-name");
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
/* 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";
|
||||
|
||||
/* Tests responsive mode links for
|
||||
* @media sidebar width and height related conditions */
|
||||
|
||||
const asyncStorage = require("devtools/shared/async-storage");
|
||||
Services.prefs.setCharPref("devtools.devices.url",
|
||||
"http://example.com/browser/devtools/client/responsive.html/test/browser/devices.json");
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("devtools.devices.url");
|
||||
asyncStorage.removeItem("devtools.devices.url_cache");
|
||||
});
|
||||
|
||||
const mgr = "resource://devtools/client/responsivedesign/responsivedesign.jsm";
|
||||
const {ResponsiveUIManager} = Cu.import(mgr, {});
|
||||
const TESTCASE_URI = TEST_BASE_HTTPS + "media-rules.html";
|
||||
const responsiveModeToggleClass = ".media-responsive-mode-toggle";
|
||||
|
||||
add_task(function* () {
|
||||
let {ui} = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
let editor = ui.editors[1];
|
||||
yield openEditor(editor);
|
||||
|
||||
let tab = gBrowser.selectedTab;
|
||||
testNumberOfLinks(editor);
|
||||
yield testMediaLink(editor, tab, ui, 2, "width", 400);
|
||||
yield testMediaLink(editor, tab, ui, 3, "height", 300);
|
||||
|
||||
yield closeRDM(tab, ui);
|
||||
doFinalChecks(editor);
|
||||
});
|
||||
|
||||
function testNumberOfLinks(editor) {
|
||||
let sidebar = editor.details.querySelector(".stylesheet-sidebar");
|
||||
let conditions = sidebar.querySelectorAll(".media-rule-condition");
|
||||
|
||||
info("Testing if media rules have the appropriate number of links");
|
||||
ok(!conditions[0].querySelector(responsiveModeToggleClass),
|
||||
"There should be no links in the first media rule.");
|
||||
ok(!conditions[1].querySelector(responsiveModeToggleClass),
|
||||
"There should be no links in the second media rule.");
|
||||
ok(conditions[2].querySelector(responsiveModeToggleClass),
|
||||
"There should be 1 responsive mode link in the media rule");
|
||||
is(conditions[3].querySelectorAll(responsiveModeToggleClass).length, 2,
|
||||
"There should be 2 responsive mode links in the media rule");
|
||||
}
|
||||
|
||||
function* testMediaLink(editor, tab, ui, itemIndex, type, value) {
|
||||
let sidebar = editor.details.querySelector(".stylesheet-sidebar");
|
||||
let conditions = sidebar.querySelectorAll(".media-rule-condition");
|
||||
|
||||
let onMediaChange = once(ui, "media-list-changed");
|
||||
|
||||
info("Launching responsive mode");
|
||||
conditions[itemIndex].querySelector(responsiveModeToggleClass).click();
|
||||
|
||||
let rdmUI = ResponsiveUIManager.getResponsiveUIForTab(tab);
|
||||
let onContentResize = waitForResizeTo(rdmUI, type, value);
|
||||
rdmUI.transitionsEnabled = false;
|
||||
|
||||
info("Waiting for the @media list to update");
|
||||
yield onMediaChange;
|
||||
yield onContentResize;
|
||||
|
||||
ok(ResponsiveUIManager.isActiveForTab(tab),
|
||||
"Responsive mode should be active.");
|
||||
conditions = sidebar.querySelectorAll(".media-rule-condition");
|
||||
ok(!conditions[itemIndex].classList.contains("media-condition-unmatched"),
|
||||
"media rule should now be matched after responsive mode is active");
|
||||
|
||||
let dimension = (yield getSizing(rdmUI))[type];
|
||||
is(dimension, value, `${type} should be properly set.`);
|
||||
}
|
||||
|
||||
function* closeRDM(tab, ui) {
|
||||
info("Closing responsive mode");
|
||||
ResponsiveUIManager.toggle(window, tab);
|
||||
let onMediaChange = waitForNEvents(ui, "media-list-changed", 2);
|
||||
yield once(ResponsiveUIManager, "off");
|
||||
yield onMediaChange;
|
||||
ok(!ResponsiveUIManager.isActiveForTab(tab),
|
||||
"Responsive mode should no longer be active.");
|
||||
}
|
||||
|
||||
function doFinalChecks(editor) {
|
||||
let sidebar = editor.details.querySelector(".stylesheet-sidebar");
|
||||
let conditions = sidebar.querySelectorAll(".media-rule-condition");
|
||||
conditions = sidebar.querySelectorAll(".media-rule-condition");
|
||||
ok(conditions[2].classList.contains("media-condition-unmatched"),
|
||||
"The width condition should now be unmatched");
|
||||
ok(conditions[3].classList.contains("media-condition-unmatched"),
|
||||
"The height condition should now be unmatched");
|
||||
}
|
||||
|
||||
/* Helpers */
|
||||
function waitForResizeTo(rdmUI, type, value) {
|
||||
return new Promise(resolve => {
|
||||
let onResize = (_, data) => {
|
||||
if (data[type] != value) {
|
||||
return;
|
||||
}
|
||||
ResponsiveUIManager.off("content-resize", onResize);
|
||||
if (rdmUI.off) {
|
||||
rdmUI.off("content-resize", onResize);
|
||||
}
|
||||
info(`Got content-resize to a ${type} of ${value}`);
|
||||
resolve();
|
||||
};
|
||||
info(`Waiting for content-resize to a ${type} of ${value}`);
|
||||
// Old RDM emits on manager
|
||||
ResponsiveUIManager.on("content-resize", onResize);
|
||||
// New RDM emits on ui
|
||||
if (rdmUI.on) {
|
||||
rdmUI.on("content-resize", onResize);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function* getSizing(rdmUI) {
|
||||
let browser = rdmUI.getViewportBrowser();
|
||||
let sizing = yield ContentTask.spawn(browser, {}, function* () {
|
||||
return {
|
||||
width: content.innerWidth,
|
||||
height: content.innerHeight
|
||||
};
|
||||
});
|
||||
return sizing;
|
||||
}
|
||||
|
||||
function openEditor(editor) {
|
||||
getLinkFor(editor).click();
|
||||
|
||||
return editor.getSourceEditor();
|
||||
}
|
||||
|
||||
function getLinkFor(editor) {
|
||||
return editor.summary.querySelector(".stylesheet-name");
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/* 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";
|
||||
|
||||
// https rather than chrome to improve coverage
|
||||
const TESTCASE_URI = TEST_BASE_HTTPS + "media-rules-sourcemaps.html";
|
||||
const MAP_PREF = "devtools.styleeditor.source-maps-enabled";
|
||||
|
||||
const LABELS = ["screen and (max-width: 320px)",
|
||||
"screen and (min-width: 1200px)"];
|
||||
const LINE_NOS = [5, 8];
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
add_task(function* () {
|
||||
Services.prefs.setBoolPref(MAP_PREF, true);
|
||||
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
yield listenForMediaChange(ui);
|
||||
|
||||
is(ui.editors.length, 1, "correct number of editors");
|
||||
|
||||
// Test editor with @media rules
|
||||
let mediaEditor = ui.editors[0];
|
||||
yield openEditor(mediaEditor);
|
||||
testMediaEditor(mediaEditor);
|
||||
|
||||
Services.prefs.clearUserPref(MAP_PREF);
|
||||
});
|
||||
|
||||
function testMediaEditor(editor) {
|
||||
let sidebar = editor.details.querySelector(".stylesheet-sidebar");
|
||||
is(sidebar.hidden, false, "sidebar is showing on editor with @media");
|
||||
|
||||
let entries = [...sidebar.querySelectorAll(".media-rule-label")];
|
||||
is(entries.length, 2, "two @media rules displayed in sidebar");
|
||||
|
||||
testRule(entries[0], LABELS[0], LINE_NOS[0]);
|
||||
testRule(entries[1], LABELS[1], LINE_NOS[1]);
|
||||
}
|
||||
|
||||
function testRule(rule, text, lineno) {
|
||||
let cond = rule.querySelector(".media-rule-condition");
|
||||
is(cond.textContent, text, "media label is correct for " + text);
|
||||
|
||||
let line = rule.querySelector(".media-rule-line");
|
||||
is(line.textContent, ":" + lineno, "correct line number shown");
|
||||
}
|
||||
|
||||
/* Helpers */
|
||||
|
||||
function openEditor(editor) {
|
||||
getLinkFor(editor).click();
|
||||
|
||||
return editor.getSourceEditor();
|
||||
}
|
||||
|
||||
function listenForMediaChange(UI) {
|
||||
let deferred = defer();
|
||||
UI.once("media-list-changed", () => {
|
||||
deferred.resolve();
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function getLinkFor(editor) {
|
||||
return editor.summary.querySelector(".stylesheet-name");
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
"use strict";
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Checks that the style editor manages to finalize its stylesheet loading phase
|
||||
// even if one stylesheet is missing, and that an error message is displayed.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE + "missing.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { ui, toolbox, panel } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
// Note that we're not testing for a specific number of stylesheet editors
|
||||
// below because the test-page is loaded with chrome:// URL and, right now,
|
||||
// that means UA stylesheets are shown. So we avoid hardcoding the number of
|
||||
// stylesheets here.
|
||||
ok(ui.editors.length, "The UI contains style sheets.");
|
||||
|
||||
let rootEl = panel.panelWindow.document.getElementById("style-editor-chrome");
|
||||
ok(!rootEl.classList.contains("loading"), "The loading indicator is hidden");
|
||||
|
||||
let notifBox = toolbox.getNotificationBox();
|
||||
let notif = notifBox.getCurrentNotification();
|
||||
ok(notif, "The notification box contains a message");
|
||||
ok(notif.label.indexOf("Style sheet could not be loaded") !== -1,
|
||||
"The error message is the correct one");
|
||||
ok(notif.label.indexOf("missing-stylesheet.css") !== -1,
|
||||
"The error message contains the missing stylesheet's URL");
|
||||
});
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/* 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";
|
||||
|
||||
// Test that selected sheet and cursor position is reset during navigation.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTPS + "simple.html";
|
||||
const NEW_URI = TEST_BASE_HTTPS + "media.html";
|
||||
|
||||
const LINE_NO = 5;
|
||||
const COL_NO = 3;
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
is(ui.editors.length, 2, "Two sheets present after load.");
|
||||
|
||||
info("Selecting the second editor");
|
||||
yield ui.selectStyleSheet(ui.editors[1].styleSheet, LINE_NO, COL_NO);
|
||||
|
||||
yield navigateToAndWaitForStyleSheets(NEW_URI, ui);
|
||||
|
||||
info("Waiting for source editor to be ready.");
|
||||
yield ui.editors[0].getSourceEditor();
|
||||
|
||||
is(ui.selectedEditor, ui.editors[0], "first editor is selected");
|
||||
|
||||
let {line, ch} = ui.selectedEditor.sourceEditor.getCursor();
|
||||
is(line, 0, "first line is selected");
|
||||
is(ch, 0, "first column is selected");
|
||||
});
|
||||
113
devtools/client/styleeditor/test/browser_styleeditor_new.js
Normal file
113
devtools/client/styleeditor/test/browser_styleeditor_new.js
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/* 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";
|
||||
|
||||
// Test that new sheets can be added and edited.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
|
||||
|
||||
const TESTCASE_CSS_SOURCE = "body{background-color:red;";
|
||||
|
||||
add_task(function* () {
|
||||
let { panel, ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
let editor = yield createNew(ui, panel.panelWindow);
|
||||
yield testInitialState(editor);
|
||||
|
||||
let originalHref = editor.styleSheet.href;
|
||||
let waitForPropertyChange = onPropertyChange(editor);
|
||||
|
||||
yield typeInEditor(editor, panel.panelWindow);
|
||||
|
||||
yield waitForPropertyChange;
|
||||
|
||||
testUpdated(editor, originalHref);
|
||||
});
|
||||
|
||||
function createNew(ui, panelWindow) {
|
||||
info("Creating a new stylesheet now");
|
||||
let deferred = defer();
|
||||
|
||||
ui.once("editor-added", (ev, editor) => {
|
||||
editor.getSourceEditor().then(deferred.resolve);
|
||||
});
|
||||
|
||||
waitForFocus(function () {
|
||||
// create a new style sheet
|
||||
let newButton = panelWindow.document
|
||||
.querySelector(".style-editor-newButton");
|
||||
ok(newButton, "'new' button exists");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(newButton, {}, panelWindow);
|
||||
}, panelWindow);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function onPropertyChange(editor) {
|
||||
let deferred = defer();
|
||||
|
||||
editor.styleSheet.on("property-change", function onProp(property) {
|
||||
// wait for text to be entered fully
|
||||
let text = editor.sourceEditor.getText();
|
||||
if (property == "ruleCount" && text == TESTCASE_CSS_SOURCE + "}") {
|
||||
editor.styleSheet.off("property-change", onProp);
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function* testInitialState(editor) {
|
||||
info("Testing the initial state of the new editor");
|
||||
|
||||
let summary = editor.summary;
|
||||
|
||||
ok(editor.sourceLoaded, "new editor is loaded when attached");
|
||||
ok(editor.isNew, "new editor has isNew flag");
|
||||
|
||||
ok(editor.sourceEditor.hasFocus(), "new editor has focus");
|
||||
|
||||
summary = editor.summary;
|
||||
let ruleCount = summary.querySelector(".stylesheet-rule-count").textContent;
|
||||
is(parseInt(ruleCount, 10), 0, "new editor initially shows 0 rules");
|
||||
|
||||
let color = yield getComputedStyleProperty({
|
||||
selector: "body",
|
||||
name: "background-color"
|
||||
});
|
||||
is(color, "rgb(255, 255, 255)",
|
||||
"content's background color is initially white");
|
||||
}
|
||||
|
||||
function typeInEditor(editor, panelWindow) {
|
||||
let deferred = defer();
|
||||
|
||||
waitForFocus(function () {
|
||||
for (let c of TESTCASE_CSS_SOURCE) {
|
||||
EventUtils.synthesizeKey(c, {}, panelWindow);
|
||||
}
|
||||
ok(editor.unsaved, "new editor has unsaved flag");
|
||||
|
||||
deferred.resolve();
|
||||
}, panelWindow);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testUpdated(editor, originalHref) {
|
||||
info("Testing the state of the new editor after editing it");
|
||||
|
||||
is(editor.sourceEditor.getText(), TESTCASE_CSS_SOURCE + "}",
|
||||
"rule bracket has been auto-closed");
|
||||
|
||||
let ruleCount = editor.summary.querySelector(".stylesheet-rule-count")
|
||||
.textContent;
|
||||
is(parseInt(ruleCount, 10), 1,
|
||||
"new editor shows 1 rule after modification");
|
||||
|
||||
is(editor.styleSheet.href, originalHref,
|
||||
"style sheet href did not change");
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/* 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";
|
||||
|
||||
// Test that 'no styles' indicator is shown if a page doesn't contain any style
|
||||
// sheets.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "nostyle.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { panel } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
let { panelWindow } = panel;
|
||||
|
||||
let root = panelWindow.document.querySelector(".splitview-root");
|
||||
ok(!root.classList.contains("loading"),
|
||||
"style editor root element does not have 'loading' class name anymore");
|
||||
|
||||
ok(root.querySelector(".empty.placeholder"), "showing 'no style' indicator");
|
||||
|
||||
let button = panelWindow.document.querySelector(".style-editor-newButton");
|
||||
ok(!button.hasAttribute("disabled"),
|
||||
"new style sheet button is enabled");
|
||||
|
||||
button = panelWindow.document.querySelector(".style-editor-importButton");
|
||||
ok(!button.hasAttribute("disabled"),
|
||||
"import button is enabled");
|
||||
});
|
||||
121
devtools/client/styleeditor/test/browser_styleeditor_opentab.js
Normal file
121
devtools/client/styleeditor/test/browser_styleeditor_opentab.js
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/* 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";
|
||||
|
||||
// A test to check the 'Open Link in new tab' functionality in the
|
||||
// context menu item for stylesheets (bug 992947).
|
||||
const TESTCASE_URI = TEST_BASE_HTTPS + "simple.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
yield rightClickStyleSheet(ui, ui.editors[0]);
|
||||
is(ui._openLinkNewTabItem.getAttribute("disabled"), "false",
|
||||
"The menu item is not disabled");
|
||||
is(ui._openLinkNewTabItem.getAttribute("hidden"), "false",
|
||||
"The menu item is not hidden");
|
||||
|
||||
let url = "https://example.com/browser/devtools/client/styleeditor/test/" +
|
||||
"simple.css";
|
||||
is(ui._contextMenuStyleSheet.href, url, "Correct URL for sheet");
|
||||
|
||||
let originalOpenUILinkIn = ui._window.openUILinkIn;
|
||||
let tabOpenedDefer = defer();
|
||||
|
||||
ui._window.openUILinkIn = newUrl => {
|
||||
// Reset the actual openUILinkIn function before proceeding.
|
||||
ui._window.openUILinkIn = originalOpenUILinkIn;
|
||||
|
||||
is(newUrl, url, "The correct tab has been opened");
|
||||
tabOpenedDefer.resolve();
|
||||
};
|
||||
|
||||
ui._openLinkNewTabItem.click();
|
||||
|
||||
info(`Waiting for a tab to open - ${url}`);
|
||||
yield tabOpenedDefer.promise;
|
||||
|
||||
yield rightClickInlineStyleSheet(ui, ui.editors[1]);
|
||||
is(ui._openLinkNewTabItem.getAttribute("disabled"), "true",
|
||||
"The menu item is disabled");
|
||||
is(ui._openLinkNewTabItem.getAttribute("hidden"), "false",
|
||||
"The menu item is not hidden");
|
||||
|
||||
yield rightClickNoStyleSheet(ui);
|
||||
is(ui._openLinkNewTabItem.getAttribute("hidden"), "true",
|
||||
"The menu item is not hidden");
|
||||
});
|
||||
|
||||
function onPopupShow(contextMenu) {
|
||||
let deferred = defer();
|
||||
contextMenu.addEventListener("popupshown", function onpopupshown() {
|
||||
contextMenu.removeEventListener("popupshown", onpopupshown);
|
||||
deferred.resolve();
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function onPopupHide(contextMenu) {
|
||||
let deferred = defer();
|
||||
contextMenu.addEventListener("popuphidden", function popuphidden() {
|
||||
contextMenu.removeEventListener("popuphidden", popuphidden);
|
||||
deferred.resolve();
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function rightClickStyleSheet(ui, editor) {
|
||||
let deferred = defer();
|
||||
|
||||
onPopupShow(ui._contextMenu).then(()=> {
|
||||
onPopupHide(ui._contextMenu).then(() => {
|
||||
deferred.resolve();
|
||||
});
|
||||
ui._contextMenu.hidePopup();
|
||||
});
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
editor.summary.querySelector(".stylesheet-name"),
|
||||
{button: 2, type: "contextmenu"},
|
||||
ui._window);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function rightClickInlineStyleSheet(ui, editor) {
|
||||
let deferred = defer();
|
||||
|
||||
onPopupShow(ui._contextMenu).then(()=> {
|
||||
onPopupHide(ui._contextMenu).then(() => {
|
||||
deferred.resolve();
|
||||
});
|
||||
ui._contextMenu.hidePopup();
|
||||
});
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
editor.summary.querySelector(".stylesheet-name"),
|
||||
{button: 2, type: "contextmenu"},
|
||||
ui._window);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function rightClickNoStyleSheet(ui) {
|
||||
let deferred = defer();
|
||||
|
||||
onPopupShow(ui._contextMenu).then(()=> {
|
||||
onPopupHide(ui._contextMenu).then(() => {
|
||||
deferred.resolve();
|
||||
});
|
||||
ui._contextMenu.hidePopup();
|
||||
});
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
ui._panelDoc.querySelector("#splitview-tpl-summary-stylesheet"),
|
||||
{button: 2, type: "contextmenu"},
|
||||
ui._window);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/* 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";
|
||||
|
||||
// Test that minified sheets are automatically prettified but other are left
|
||||
// untouched.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "minified.html";
|
||||
|
||||
/*
|
||||
body {
|
||||
background:white;
|
||||
}
|
||||
div {
|
||||
font-size:4em;
|
||||
color:red
|
||||
}
|
||||
span {
|
||||
color:green;
|
||||
}
|
||||
*/
|
||||
const PRETTIFIED_SOURCE = "" +
|
||||
"body \{\r?\n" +
|
||||
"\tbackground\:white;\r?\n" +
|
||||
"\}\r?\n" +
|
||||
"div \{\r?\n" +
|
||||
"\tfont\-size\:4em;\r?\n" +
|
||||
"\tcolor\:red\r?\n" +
|
||||
"\}\r?\n" +
|
||||
"span \{\r?\n" +
|
||||
"\tcolor\:green;\r?\n" +
|
||||
"\}\r?\n";
|
||||
|
||||
/*
|
||||
body { background: red; }
|
||||
div {
|
||||
font-size: 5em;
|
||||
color: red
|
||||
}
|
||||
*/
|
||||
const ORIGINAL_SOURCE = "" +
|
||||
"body \{ background\: red; \}\r?\n" +
|
||||
"div \{\r?\n" +
|
||||
"font\-size\: 5em;\r?\n" +
|
||||
"color\: red\r?\n" +
|
||||
"\}";
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
is(ui.editors.length, 2, "Two sheets present.");
|
||||
|
||||
info("Testing minified style sheet.");
|
||||
let editor = yield ui.editors[0].getSourceEditor();
|
||||
|
||||
let prettifiedSourceRE = new RegExp(PRETTIFIED_SOURCE);
|
||||
ok(prettifiedSourceRE.test(editor.sourceEditor.getText()),
|
||||
"minified source has been prettified automatically");
|
||||
|
||||
info("Selecting second, non-minified style sheet.");
|
||||
yield ui.selectStyleSheet(ui.editors[1].styleSheet);
|
||||
|
||||
editor = ui.editors[1];
|
||||
|
||||
let originalSourceRE = new RegExp(ORIGINAL_SOURCE);
|
||||
ok(originalSourceRE.test(editor.sourceEditor.getText()),
|
||||
"non-minified source has been left untouched");
|
||||
});
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/* 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 test makes sure that the style editor does not store any
|
||||
// content CSS files in the permanent cache when opened from PB mode.
|
||||
|
||||
const TEST_URL = "http://" + TEST_HOST + "/browser/devtools/client/" +
|
||||
"styleeditor/test/test_private.html";
|
||||
const {LoadContextInfo} =
|
||||
Cu.import("resource://gre/modules/LoadContextInfo.jsm", {});
|
||||
const cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
|
||||
.getService(Ci.nsICacheStorageService);
|
||||
|
||||
add_task(function* () {
|
||||
info("Opening a new private window");
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
yield waitForDelayedStartupFinished(win);
|
||||
|
||||
info("Clearing the browser cache");
|
||||
cache.clear();
|
||||
|
||||
let { toolbox, ui } = yield openStyleEditorForURL(TEST_URL, win);
|
||||
|
||||
is(ui.editors.length, 1, "The style editor contains one sheet.");
|
||||
let editor = ui.editors[0];
|
||||
|
||||
yield editor.getSourceEditor();
|
||||
yield checkDiskCacheFor(TEST_HOST);
|
||||
|
||||
yield toolbox.destroy();
|
||||
|
||||
let onUnload = new Promise(done => {
|
||||
win.addEventListener("unload", function listener(event) {
|
||||
if (event.target == win.document) {
|
||||
win.removeEventListener("unload", listener);
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
win.close();
|
||||
yield onUnload;
|
||||
});
|
||||
|
||||
function checkDiskCacheFor(host) {
|
||||
let foundPrivateData = false;
|
||||
let deferred = defer();
|
||||
|
||||
Visitor.prototype = {
|
||||
onCacheStorageInfo: function (num) {
|
||||
info("disk storage contains " + num + " entries");
|
||||
},
|
||||
onCacheEntryInfo: function (uri) {
|
||||
let urispec = uri.asciiSpec;
|
||||
info(urispec);
|
||||
foundPrivateData |= urispec.includes(host);
|
||||
},
|
||||
onCacheEntryVisitCompleted: function () {
|
||||
is(foundPrivateData, false, "web content present in disk cache");
|
||||
deferred.resolve();
|
||||
}
|
||||
};
|
||||
function Visitor() {}
|
||||
|
||||
let storage = cache.diskCacheStorage(LoadContextInfo.default, false);
|
||||
storage.asyncVisitStorage(new Visitor(),
|
||||
/* Do walk entries */
|
||||
true);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function waitForDelayedStartupFinished(win) {
|
||||
let deferred = defer();
|
||||
Services.obs.addObserver(function observer(subject, topic) {
|
||||
if (win == subject) {
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
deferred.resolve();
|
||||
}
|
||||
}, "browser-delayed-startup-finished", false);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/* 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";
|
||||
|
||||
// Test that selected sheet and cursor position persists during reload.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTPS + "simple.html";
|
||||
|
||||
const LINE_NO = 5;
|
||||
const COL_NO = 3;
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
is(ui.editors.length, 2, "Two sheets present after load.");
|
||||
|
||||
info("Selecting the second editor");
|
||||
yield ui.selectStyleSheet(ui.editors[1].styleSheet, LINE_NO, COL_NO);
|
||||
|
||||
yield reloadPageAndWaitForStyleSheets(ui);
|
||||
|
||||
is(ui.editors.length, 2, "Two sheets present after reload.");
|
||||
|
||||
info("Waiting for source editor to be ready.");
|
||||
yield ui.editors[1].getSourceEditor();
|
||||
|
||||
is(ui.selectedEditor, ui.editors[1],
|
||||
"second editor is selected after reload");
|
||||
|
||||
let {line, ch} = ui.selectedEditor.sourceEditor.getCursor();
|
||||
is(line, LINE_NO, "correct line selected");
|
||||
is(ch, COL_NO, "correct column selected");
|
||||
});
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/* 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";
|
||||
|
||||
// Test that editor scrolls to correct line if it's selected with
|
||||
// * selectStyleSheet (specified line)
|
||||
// * click on the sidebar item (line before the editor was unselected)
|
||||
// See bug 1148086.
|
||||
|
||||
const SIMPLE = TEST_BASE_HTTP + "simple.css";
|
||||
const LONG = TEST_BASE_HTTP + "doc_long.css";
|
||||
const DOCUMENT_WITH_LONG_SHEET = "data:text/html;charset=UTF-8," +
|
||||
encodeURIComponent(
|
||||
["<!DOCTYPE html>",
|
||||
"<html>",
|
||||
" <head>",
|
||||
" <title>Editor scroll test page</title>",
|
||||
' <link rel="stylesheet" type="text/css" href="' + SIMPLE + '">',
|
||||
' <link rel="stylesheet" type="text/css" href="' + LONG + '">',
|
||||
" </head>",
|
||||
" <body>Editor scroll test page</body>",
|
||||
"</html>"
|
||||
].join("\n"));
|
||||
const LINE_TO_SELECT = 201;
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(DOCUMENT_WITH_LONG_SHEET);
|
||||
|
||||
is(ui.editors.length, 2, "Two editors present.");
|
||||
|
||||
let simpleEditor = ui.editors[0];
|
||||
let longEditor = ui.editors[1];
|
||||
|
||||
info(`Selecting doc_long.css and scrolling to line ${LINE_TO_SELECT}`);
|
||||
|
||||
// We need to wait for editor-selected if we want to check the scroll
|
||||
// position as scrolling occurs after selectStyleSheet resolves but before the
|
||||
// event is emitted.
|
||||
let selectEventPromise = waitForEditorToBeSelected(longEditor, ui);
|
||||
ui.selectStyleSheet(longEditor.styleSheet, LINE_TO_SELECT);
|
||||
yield selectEventPromise;
|
||||
|
||||
info("Checking that the correct line is visible after initial load");
|
||||
|
||||
let { from, to } = longEditor.sourceEditor.getViewport();
|
||||
info(`Lines ${from}-${to} are visible (expected ${LINE_TO_SELECT}).`);
|
||||
|
||||
ok(from <= LINE_TO_SELECT, "The editor scrolled too much.");
|
||||
ok(to >= LINE_TO_SELECT, "The editor scrolled too little.");
|
||||
|
||||
let initialScrollTop = longEditor.sourceEditor.getScrollInfo().top;
|
||||
info(`Storing scrollTop = ${initialScrollTop} for later comparison.`);
|
||||
|
||||
info("Selecting the first editor (simple.css)");
|
||||
yield ui.selectStyleSheet(simpleEditor.styleSheet);
|
||||
|
||||
info("Selecting doc_long.css again.");
|
||||
selectEventPromise = waitForEditorToBeSelected(longEditor, ui);
|
||||
|
||||
// Can't use ui.selectStyleSheet here as it will scroll the editor back to top
|
||||
// and we want to check that the previous scroll position is restored.
|
||||
let summary = yield ui.getEditorSummary(longEditor);
|
||||
ui._view.activeSummary = summary;
|
||||
|
||||
info("Waiting for doc_long.css to be selected.");
|
||||
yield selectEventPromise;
|
||||
|
||||
let scrollTop = longEditor.sourceEditor.getScrollInfo().top;
|
||||
is(scrollTop, initialScrollTop,
|
||||
"Scroll top was restored after the sheet was selected again.");
|
||||
});
|
||||
|
||||
/**
|
||||
* A helper that waits "editor-selected" event for given editor.
|
||||
*
|
||||
* @param {StyleSheetEditor} editor
|
||||
* The editor to wait for.
|
||||
* @param {StyleEditorUI} ui
|
||||
* The StyleEditorUI the editor belongs to.
|
||||
*/
|
||||
var waitForEditorToBeSelected = Task.async(function* (editor, ui) {
|
||||
info(`Waiting for ${editor.friendlyName} to be selected.`);
|
||||
let selected = yield ui.once("editor-selected");
|
||||
while (selected != editor) {
|
||||
info(`Ignored editor-selected for editor ${editor.friendlyName}.`);
|
||||
selected = yield ui.once("editor-selected");
|
||||
}
|
||||
|
||||
info(`Got editor-selected for ${editor.friendlyName}.`);
|
||||
});
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/* 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";
|
||||
|
||||
// Test that StyleEditorUI.selectStyleSheet selects the correct sheet, line and
|
||||
// column.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTPS + "simple.html";
|
||||
|
||||
const LINE_NO = 5;
|
||||
const COL_NO = 0;
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
let editor = ui.editors[1];
|
||||
|
||||
info("Selecting style sheet #1.");
|
||||
yield ui.selectStyleSheet(editor.styleSheet.href, LINE_NO);
|
||||
|
||||
is(ui.selectedEditor, ui.editors[1], "Second editor is selected.");
|
||||
let {line, ch} = ui.selectedEditor.sourceEditor.getCursor();
|
||||
|
||||
is(line, LINE_NO, "correct line selected");
|
||||
is(ch, COL_NO, "correct column selected");
|
||||
});
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/* 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";
|
||||
|
||||
// Covers the case from Bug 1128747, where loading a sourcemapped
|
||||
// file prevents the correct editor from being selected on load,
|
||||
// and causes a second iframe to be appended when the user clicks
|
||||
// editor in the list.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTPS + "sourcemaps-large.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
yield openEditor(ui.editors[0]);
|
||||
let iframes = ui.selectedEditor.details.querySelectorAll("iframe");
|
||||
|
||||
is(iframes.length, 1, "There is only one editor iframe");
|
||||
ok(ui.selectedEditor.summary.classList.contains("splitview-active"),
|
||||
"The editor is selected");
|
||||
});
|
||||
|
||||
function openEditor(editor) {
|
||||
getLinkFor(editor).click();
|
||||
|
||||
return editor.getSourceEditor();
|
||||
}
|
||||
|
||||
function getLinkFor(editor) {
|
||||
return editor.summary.querySelector(".stylesheet-name");
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
/* 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 TESTCASE_URI_HTML = TEST_BASE_HTTP + "sourcemaps-watching.html";
|
||||
const TESTCASE_URI_CSS = TEST_BASE_HTTP + "sourcemap-css/sourcemaps.css";
|
||||
const TESTCASE_URI_REG_CSS = TEST_BASE_HTTP + "simple.css";
|
||||
const TESTCASE_URI_SCSS = TEST_BASE_HTTP + "sourcemap-sass/sourcemaps.scss";
|
||||
const TESTCASE_URI_MAP = TEST_BASE_HTTP + "sourcemap-css/sourcemaps.css.map";
|
||||
const TESTCASE_SCSS_NAME = "sourcemaps.scss";
|
||||
|
||||
const TRANSITIONS_PREF = "devtools.styleeditor.transitions";
|
||||
|
||||
const CSS_TEXT = "* { color: blue }";
|
||||
|
||||
const {FileUtils} = Components.utils.import("resource://gre/modules/FileUtils.jsm", {});
|
||||
const {NetUtil} = Components.utils.import("resource://gre/modules/NetUtil.jsm", {});
|
||||
|
||||
add_task(function* () {
|
||||
yield new Promise(resolve => {
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
[TRANSITIONS_PREF, false]
|
||||
]}, resolve);
|
||||
});
|
||||
|
||||
// copy all our files over so we don't screw them up for other tests
|
||||
let HTMLFile = yield copy(TESTCASE_URI_HTML, ["sourcemaps.html"]);
|
||||
let CSSFile = yield copy(TESTCASE_URI_CSS,
|
||||
["sourcemap-css", "sourcemaps.css"]);
|
||||
yield copy(TESTCASE_URI_SCSS, ["sourcemap-sass", "sourcemaps.scss"]);
|
||||
yield copy(TESTCASE_URI_MAP, ["sourcemap-css", "sourcemaps.css.map"]);
|
||||
yield copy(TESTCASE_URI_REG_CSS, ["simple.css"]);
|
||||
|
||||
let uri = Services.io.newFileURI(HTMLFile);
|
||||
let testcaseURI = uri.resolve("");
|
||||
|
||||
let { ui } = yield openStyleEditorForURL(testcaseURI);
|
||||
|
||||
let editor = ui.editors[1];
|
||||
if (getStylesheetNameFor(editor) != TESTCASE_SCSS_NAME) {
|
||||
editor = ui.editors[2];
|
||||
}
|
||||
|
||||
is(getStylesheetNameFor(editor), TESTCASE_SCSS_NAME, "found scss editor");
|
||||
|
||||
let link = getLinkFor(editor);
|
||||
link.click();
|
||||
|
||||
yield editor.getSourceEditor();
|
||||
|
||||
let color = yield getComputedStyleProperty({selector: "div", name: "color"});
|
||||
is(color, "rgb(255, 0, 102)", "div is red before saving file");
|
||||
|
||||
// let styleApplied = defer();
|
||||
let styleApplied = editor.once("style-applied");
|
||||
|
||||
yield pauseForTimeChange();
|
||||
|
||||
// Edit and save Sass in the editor. This will start off a file-watching
|
||||
// process waiting for the CSS file to change.
|
||||
yield editSCSS(editor);
|
||||
|
||||
// We can't run Sass or another compiler, so we fake it by just
|
||||
// directly changing the CSS file.
|
||||
yield editCSSFile(CSSFile);
|
||||
|
||||
info("wrote to CSS file, waiting for style-applied event");
|
||||
|
||||
yield styleApplied;
|
||||
|
||||
color = yield getComputedStyleProperty({selector: "div", name: "color"});
|
||||
is(color, "rgb(0, 0, 255)", "div is blue after saving file");
|
||||
});
|
||||
|
||||
function editSCSS(editor) {
|
||||
let deferred = defer();
|
||||
|
||||
editor.sourceEditor.setText(CSS_TEXT);
|
||||
|
||||
editor.saveToFile(null, function (file) {
|
||||
ok(file, "Scss file should be saved");
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function editCSSFile(CSSFile) {
|
||||
return write(CSS_TEXT, CSSFile);
|
||||
}
|
||||
|
||||
function pauseForTimeChange() {
|
||||
let deferred = defer();
|
||||
|
||||
// We have to wait for the system time to turn over > 1000 ms so that
|
||||
// our file's last change time will show a change. This reflects what
|
||||
// would happen in real life with a user manually saving the file.
|
||||
setTimeout(deferred.resolve, 2000);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/* Helpers */
|
||||
|
||||
function getLinkFor(editor) {
|
||||
return editor.summary.querySelector(".stylesheet-name");
|
||||
}
|
||||
|
||||
function getStylesheetNameFor(editor) {
|
||||
return editor.summary.querySelector(".stylesheet-name > label")
|
||||
.getAttribute("value");
|
||||
}
|
||||
|
||||
function copy(srcChromeURL, destFilePath) {
|
||||
let destFile = FileUtils.getFile("ProfD", destFilePath);
|
||||
return write(read(srcChromeURL), destFile);
|
||||
}
|
||||
|
||||
function read(srcChromeURL) {
|
||||
let scriptableStream = Cc["@mozilla.org/scriptableinputstream;1"]
|
||||
.getService(Ci.nsIScriptableInputStream);
|
||||
|
||||
let channel = NetUtil.newChannel({
|
||||
uri: srcChromeURL,
|
||||
loadUsingSystemPrincipal: true
|
||||
});
|
||||
let input = channel.open2();
|
||||
scriptableStream.init(input);
|
||||
|
||||
let data = "";
|
||||
while (input.available()) {
|
||||
data = data.concat(scriptableStream.read(input.available()));
|
||||
}
|
||||
scriptableStream.close();
|
||||
input.close();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function write(data, file) {
|
||||
let deferred = defer();
|
||||
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
|
||||
converter.charset = "UTF-8";
|
||||
|
||||
let istream = converter.convertToInputStream(data);
|
||||
let ostream = FileUtils.openSafeFileOutputStream(file);
|
||||
|
||||
NetUtil.asyncCopy(istream, ostream, function (status) {
|
||||
if (!Components.isSuccessCode(status)) {
|
||||
info("Coudln't write to " + file.path);
|
||||
return;
|
||||
}
|
||||
deferred.resolve(file);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
|
@ -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";
|
||||
|
||||
// https rather than chrome to improve coverage
|
||||
const TESTCASE_URI = TEST_BASE_HTTPS + "sourcemaps.html";
|
||||
const PREF = "devtools.styleeditor.source-maps-enabled";
|
||||
|
||||
const contents = {
|
||||
"sourcemaps.scss": [
|
||||
"",
|
||||
"$paulrougetpink: #f06;",
|
||||
"",
|
||||
"div {",
|
||||
" color: $paulrougetpink;",
|
||||
"}",
|
||||
"",
|
||||
"span {",
|
||||
" background-color: #EEE;",
|
||||
"}"
|
||||
].join("\n"),
|
||||
"contained.scss": [
|
||||
"$pink: #f06;",
|
||||
"",
|
||||
"#header {",
|
||||
" color: $pink;",
|
||||
"}"
|
||||
].join("\n"),
|
||||
"sourcemaps.css": [
|
||||
"div {",
|
||||
" color: #ff0066; }",
|
||||
"",
|
||||
"span {",
|
||||
" background-color: #EEE; }",
|
||||
"",
|
||||
"/*# sourceMappingURL=sourcemaps.css.map */"
|
||||
].join("\n"),
|
||||
"contained.css": [
|
||||
"#header {",
|
||||
" color: #f06; }",
|
||||
"",
|
||||
"/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJma" +
|
||||
"WxlIjoiIiwic291cmNlcyI6WyJzYXNzL2NvbnRhaW5lZC5zY3NzIl0sIm5hbWVzIjpbXSwi" +
|
||||
"bWFwcGluZ3MiOiJBQUVBO0VBQ0UsT0FISyIsInNvdXJjZXNDb250ZW50IjpbIiRwaW5rOiA" +
|
||||
"jZjA2O1xuXG4jaGVhZGVyIHtcbiAgY29sb3I6ICRwaW5rO1xufSJdfQ==*/"
|
||||
].join("\n"),
|
||||
"test-stylus.styl": [
|
||||
"paulrougetpink = #f06;",
|
||||
"",
|
||||
"div",
|
||||
" color: paulrougetpink",
|
||||
"",
|
||||
"span",
|
||||
" background-color: #EEE",
|
||||
""
|
||||
].join("\n"),
|
||||
"test-stylus.css": [
|
||||
"div {",
|
||||
" color: #f06;",
|
||||
"}",
|
||||
"span {",
|
||||
" background-color: #eee;",
|
||||
"}",
|
||||
"/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb" +
|
||||
"3VyY2VzIjpbInRlc3Qtc3R5bHVzLnN0eWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFB" +
|
||||
"RUE7RUFDRSxPQUFPLEtBQVA7O0FBRUY7RUFDRSxrQkFBa0IsS0FBbEIiLCJmaWxlIjoidGV" +
|
||||
"zdC1zdHlsdXMuY3NzIiwic291cmNlc0NvbnRlbnQiOlsicGF1bHJvdWdldHBpbmsgPSAjZj" +
|
||||
"A2O1xuXG5kaXZcbiAgY29sb3I6IHBhdWxyb3VnZXRwaW5rXG5cbnNwYW5cbiAgYmFja2dyb" +
|
||||
"3VuZC1jb2xvcjogI0VFRVxuIl19 */"
|
||||
].join("\n")
|
||||
};
|
||||
|
||||
const cssNames = ["sourcemaps.css", "contained.css", "test-stylus.css"];
|
||||
const origNames = ["sourcemaps.scss", "contained.scss", "test-stylus.styl"];
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
add_task(function* () {
|
||||
let {ui} = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
is(ui.editors.length, 4,
|
||||
"correct number of editors with source maps enabled");
|
||||
|
||||
// Test first plain css editor
|
||||
testFirstEditor(ui.editors[0]);
|
||||
|
||||
// Test Scss editors
|
||||
yield testEditor(ui.editors[1], origNames);
|
||||
yield testEditor(ui.editors[2], origNames);
|
||||
yield testEditor(ui.editors[3], origNames);
|
||||
|
||||
// Test disabling original sources
|
||||
yield togglePref(ui);
|
||||
|
||||
is(ui.editors.length, 4, "correct number of editors after pref toggled");
|
||||
|
||||
// Test CSS editors
|
||||
yield testEditor(ui.editors[1], cssNames);
|
||||
yield testEditor(ui.editors[2], cssNames);
|
||||
yield testEditor(ui.editors[3], cssNames);
|
||||
|
||||
Services.prefs.clearUserPref(PREF);
|
||||
});
|
||||
|
||||
function testFirstEditor(editor) {
|
||||
let name = getStylesheetNameFor(editor);
|
||||
is(name, "simple.css", "First style sheet display name is correct");
|
||||
}
|
||||
|
||||
function testEditor(editor, possibleNames) {
|
||||
let name = getStylesheetNameFor(editor);
|
||||
ok(possibleNames.indexOf(name) >= 0, name + " editor name is correct");
|
||||
|
||||
return openEditor(editor).then(() => {
|
||||
let expectedText = contents[name];
|
||||
|
||||
let text = editor.sourceEditor.getText();
|
||||
|
||||
is(text, expectedText, name + " editor contains expected text");
|
||||
});
|
||||
}
|
||||
|
||||
/* Helpers */
|
||||
|
||||
function togglePref(UI) {
|
||||
let editorsPromise = UI.once("stylesheets-reset");
|
||||
let selectedPromise = UI.once("editor-selected");
|
||||
|
||||
Services.prefs.setBoolPref(PREF, false);
|
||||
|
||||
return promise.all([editorsPromise, selectedPromise]);
|
||||
}
|
||||
|
||||
function openEditor(editor) {
|
||||
getLinkFor(editor).click();
|
||||
|
||||
return editor.getSourceEditor();
|
||||
}
|
||||
|
||||
function getLinkFor(editor) {
|
||||
return editor.summary.querySelector(".stylesheet-name");
|
||||
}
|
||||
|
||||
function getStylesheetNameFor(editor) {
|
||||
return editor.summary.querySelector(".stylesheet-name > label")
|
||||
.getAttribute("value");
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/* 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";
|
||||
|
||||
// https rather than chrome to improve coverage
|
||||
const TESTCASE_URI = TEST_BASE_HTTPS + "sourcemaps-inline.html";
|
||||
const PREF = "devtools.styleeditor.source-maps-enabled";
|
||||
|
||||
const sassContent = `body {
|
||||
background-color: black;
|
||||
& > h1 {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const cssContent = `body {
|
||||
background-color: black;
|
||||
}
|
||||
body > h1 {
|
||||
color: white;
|
||||
}
|
||||
` +
|
||||
"/*# sourceMappingURL=data:application/json;base64,ewoidmVyc2lvbiI6IDMsCiJtY" +
|
||||
"XBwaW5ncyI6ICJBQUFBLElBQUs7RUFDSCxnQkFBZ0IsRUFBRSxLQUFLO0VBQ3ZCLFNBQU87SUFD" +
|
||||
"TCxLQUFLLEVBQUUsS0FBSyIsCiJzb3VyY2VzIjogWyJ0ZXN0LnNjc3MiXSwKInNvdXJjZXNDb25" +
|
||||
"0ZW50IjogWyJib2R5IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogYmxhY2s7XG4gICYgPiBoMSB7XG" +
|
||||
"4gICAgY29sb3I6IHdoaXRlO1xuICB9XG59XG4iXSwKIm5hbWVzIjogW10sCiJmaWxlIjogInRlc" +
|
||||
"3QuY3NzIgp9Cg== */";
|
||||
|
||||
add_task(function* () {
|
||||
let {ui} = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
is(ui.editors.length, 1,
|
||||
"correct number of editors with source maps enabled");
|
||||
|
||||
yield testEditor(ui.editors[0], "test.scss", sassContent);
|
||||
|
||||
// Test disabling original sources
|
||||
yield togglePref(ui);
|
||||
|
||||
is(ui.editors.length, 1, "correct number of editors after pref toggled");
|
||||
|
||||
// Test CSS editors
|
||||
yield testEditor(ui.editors[0], "<inline style sheet #1>", cssContent);
|
||||
|
||||
Services.prefs.clearUserPref(PREF);
|
||||
});
|
||||
|
||||
function* testEditor(editor, expectedName, expectedText) {
|
||||
let name = getStylesheetNameFor(editor);
|
||||
is(expectedName, name, name + " editor name is correct");
|
||||
|
||||
yield openEditor(editor);
|
||||
let text = editor.sourceEditor.getText();
|
||||
is(text, expectedText, name + " editor contains expected text");
|
||||
}
|
||||
|
||||
/* Helpers */
|
||||
|
||||
function togglePref(UI) {
|
||||
let editorsPromise = UI.once("stylesheets-reset");
|
||||
let selectedPromise = UI.once("editor-selected");
|
||||
|
||||
Services.prefs.setBoolPref(PREF, false);
|
||||
|
||||
return promise.all([editorsPromise, selectedPromise]);
|
||||
}
|
||||
|
||||
function openEditor(editor) {
|
||||
getLinkFor(editor).click();
|
||||
|
||||
return editor.getSourceEditor();
|
||||
}
|
||||
|
||||
function getLinkFor(editor) {
|
||||
return editor.summary.querySelector(".stylesheet-name");
|
||||
}
|
||||
|
||||
function getStylesheetNameFor(editor) {
|
||||
return editor.summary.querySelector(".stylesheet-name > label")
|
||||
.getAttribute("value");
|
||||
}
|
||||
|
|
@ -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/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the style sheet list can be navigated with keyboard.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "four.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { panel, ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
info("Waiting for source editor to load.");
|
||||
yield ui.editors[0].getSourceEditor();
|
||||
|
||||
let selected = ui.once("editor-selected");
|
||||
|
||||
info("Testing keyboard navigation on the sheet list.");
|
||||
testKeyboardNavigation(ui.editors[0], panel);
|
||||
|
||||
info("Waiting for editor #2 to be selected due to keyboard navigation.");
|
||||
yield selected;
|
||||
|
||||
ok(ui.editors[2].sourceEditor.hasFocus(), "Editor #2 has focus.");
|
||||
});
|
||||
|
||||
function getStylesheetNameLinkFor(editor) {
|
||||
return editor.summary.querySelector(".stylesheet-name");
|
||||
}
|
||||
|
||||
function testKeyboardNavigation(editor, panel) {
|
||||
let panelWindow = panel.panelWindow;
|
||||
let ui = panel.UI;
|
||||
waitForFocus(function () {
|
||||
let summary = editor.summary;
|
||||
EventUtils.synthesizeMouseAtCenter(summary, {}, panelWindow);
|
||||
|
||||
let item = getStylesheetNameLinkFor(ui.editors[0]);
|
||||
is(panelWindow.document.activeElement, item,
|
||||
"editor 0 item is the active element");
|
||||
|
||||
EventUtils.synthesizeKey("VK_DOWN", {}, panelWindow);
|
||||
item = getStylesheetNameLinkFor(ui.editors[1]);
|
||||
is(panelWindow.document.activeElement, item,
|
||||
"editor 1 item is the active element");
|
||||
|
||||
EventUtils.synthesizeKey("VK_HOME", {}, panelWindow);
|
||||
item = getStylesheetNameLinkFor(ui.editors[0]);
|
||||
is(panelWindow.document.activeElement, item,
|
||||
"fist editor item is the active element");
|
||||
|
||||
EventUtils.synthesizeKey("VK_END", {}, panelWindow);
|
||||
item = getStylesheetNameLinkFor(ui.editors[3]);
|
||||
is(panelWindow.document.activeElement, item,
|
||||
"last editor item is the active element");
|
||||
|
||||
EventUtils.synthesizeKey("VK_UP", {}, panelWindow);
|
||||
item = getStylesheetNameLinkFor(ui.editors[2]);
|
||||
is(panelWindow.document.activeElement, item,
|
||||
"editor 2 item is the active element");
|
||||
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, panelWindow);
|
||||
// this will attach and give focus editor 2
|
||||
}, panelWindow);
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/* 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";
|
||||
|
||||
// Test that resizing the source editor container doesn't move the caret.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
|
||||
|
||||
const {Toolbox} = require("devtools/client/framework/toolbox");
|
||||
|
||||
add_task(function* () {
|
||||
let { toolbox, ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
is(ui.editors.length, 2, "There are 2 style sheets initially");
|
||||
|
||||
info("Changing toolbox host to a window.");
|
||||
yield toolbox.switchHost(Toolbox.HostType.WINDOW);
|
||||
|
||||
let editor = yield ui.editors[0].getSourceEditor();
|
||||
let originalSourceEditor = editor.sourceEditor;
|
||||
|
||||
let hostWindow = toolbox.win.parent;
|
||||
let originalWidth = hostWindow.outerWidth;
|
||||
let originalHeight = hostWindow.outerHeight;
|
||||
|
||||
// to check the caret is preserved
|
||||
originalSourceEditor.setCursor(originalSourceEditor.getPosition(4));
|
||||
|
||||
info("Resizing window.");
|
||||
hostWindow.resizeTo(120, 480);
|
||||
|
||||
let sourceEditor = ui.editors[0].sourceEditor;
|
||||
is(sourceEditor, originalSourceEditor,
|
||||
"the editor still references the same Editor instance");
|
||||
|
||||
is(sourceEditor.getOffset(sourceEditor.getCursor()), 4,
|
||||
"the caret position has been preserved");
|
||||
|
||||
info("Restoring window to original size.");
|
||||
hostWindow.resizeTo(originalWidth, originalHeight);
|
||||
});
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
// Restore the host type for other tests.
|
||||
Services.prefs.clearUserPref("devtools.toolbox.host");
|
||||
});
|
||||
72
devtools/client/styleeditor/test/browser_styleeditor_sync.js
Normal file
72
devtools/client/styleeditor/test/browser_styleeditor_sync.js
Normal 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/ */
|
||||
"use strict";
|
||||
|
||||
// Test that changes in the style inspector are synchronized into the
|
||||
// style editor.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "sync.html";
|
||||
|
||||
const expectedText = `
|
||||
body {
|
||||
border-width: 15px;
|
||||
/*! color: red; */
|
||||
}
|
||||
|
||||
#testid {
|
||||
/*! font-size: 4em; */
|
||||
}
|
||||
`;
|
||||
|
||||
function* closeAndReopenToolbox() {
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
yield gDevTools.closeToolbox(target);
|
||||
let { ui: newui } = yield openStyleEditor();
|
||||
return newui;
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab(TESTCASE_URI);
|
||||
let { inspector, view } = yield openRuleView();
|
||||
yield selectNode("#testid", inspector);
|
||||
let ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||
|
||||
// Disable the "font-size" property.
|
||||
let propEditor = ruleEditor.rule.textProps[0].editor;
|
||||
let onModification = view.once("ruleview-changed");
|
||||
propEditor.enable.click();
|
||||
yield onModification;
|
||||
|
||||
// Disable the "color" property. Note that this property is in a
|
||||
// rule that also contains a non-inherited property -- so this test
|
||||
// is also testing that property editing works properly in this
|
||||
// situation.
|
||||
ruleEditor = getRuleViewRuleEditor(view, 3);
|
||||
propEditor = ruleEditor.rule.textProps[1].editor;
|
||||
onModification = view.once("ruleview-changed");
|
||||
propEditor.enable.click();
|
||||
yield onModification;
|
||||
|
||||
let { ui } = yield openStyleEditor();
|
||||
|
||||
let editor = yield ui.editors[0].getSourceEditor();
|
||||
let text = editor.sourceEditor.getText();
|
||||
is(text, expectedText, "style inspector changes are synced");
|
||||
|
||||
// Close and reopen the toolbox, to see that the edited text remains
|
||||
// available.
|
||||
ui = yield closeAndReopenToolbox();
|
||||
editor = yield ui.editors[0].getSourceEditor();
|
||||
text = editor.sourceEditor.getText();
|
||||
is(text, expectedText, "changes remain after close and reopen");
|
||||
|
||||
// For the time being, the actor does not update the style's owning
|
||||
// node's textContent. See bug 1205380.
|
||||
let textContent = yield ContentTask.spawn(gBrowser.selectedBrowser, null,
|
||||
function* () {
|
||||
return content.document.querySelector("style").textContent;
|
||||
});
|
||||
|
||||
isnot(textContent, expectedText, "changes not written back to style node");
|
||||
});
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/* 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";
|
||||
|
||||
// Test that adding a new rule is synced to the style editor.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "sync.html";
|
||||
|
||||
const expectedText = `
|
||||
body {
|
||||
border-width: 15px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
#testid {
|
||||
font-size: 4em;
|
||||
/*! background-color: yellow; */
|
||||
}
|
||||
`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab(TESTCASE_URI);
|
||||
let { inspector, view } = yield openRuleView();
|
||||
yield selectNode("#testid", inspector);
|
||||
|
||||
info("Focusing a new property name in the rule-view");
|
||||
let ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||
let editor = yield focusEditableField(view, ruleEditor.closeBrace);
|
||||
is(inplaceEditor(ruleEditor.newPropSpan), editor,
|
||||
"The new property editor has focus");
|
||||
|
||||
let input = editor.input;
|
||||
input.value = "/* background-color: yellow; */";
|
||||
|
||||
info("Pressing return to commit and focus the new value field");
|
||||
let onModifications = view.once("ruleview-changed");
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
|
||||
yield onModifications;
|
||||
|
||||
let { ui } = yield openStyleEditor();
|
||||
let sourceEditor = yield ui.editors[0].getSourceEditor();
|
||||
let text = sourceEditor.sourceEditor.getText();
|
||||
is(text, expectedText, "selector edits are synced");
|
||||
});
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/* 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";
|
||||
|
||||
// Test that adding a new rule is synced to the style editor.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "sync.html";
|
||||
|
||||
const expectedText = `
|
||||
#testid {
|
||||
}`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab(TESTCASE_URI);
|
||||
let { inspector, view } = yield openRuleView();
|
||||
yield selectNode("#testid", inspector);
|
||||
|
||||
let onRuleViewChanged = once(view, "ruleview-changed");
|
||||
view.addRuleButton.click();
|
||||
yield onRuleViewChanged;
|
||||
|
||||
let { ui } = yield openStyleEditor();
|
||||
|
||||
info("Selecting the second editor");
|
||||
yield ui.selectStyleSheet(ui.editors[1].styleSheet);
|
||||
|
||||
let editor = ui.editors[1];
|
||||
let text = editor.sourceEditor.getText();
|
||||
is(text, expectedText, "selector edits are synced");
|
||||
});
|
||||
|
|
@ -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/ */
|
||||
"use strict";
|
||||
|
||||
// Test that changes in the style inspector are synchronized into the
|
||||
// style editor.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "sync.html";
|
||||
|
||||
const expectedText = `
|
||||
body {
|
||||
border-width: 15px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
#testid {
|
||||
/*! font-size: 4em; */
|
||||
}
|
||||
`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab(TESTCASE_URI);
|
||||
|
||||
let { inspector, view, toolbox } = yield openRuleView();
|
||||
|
||||
// In this test, make sure the style editor is open before making
|
||||
// changes in the inspector.
|
||||
let { ui } = yield openStyleEditor();
|
||||
let editor = yield ui.editors[0].getSourceEditor();
|
||||
|
||||
let onEditorChange = defer();
|
||||
editor.sourceEditor.on("change", onEditorChange.resolve);
|
||||
|
||||
yield toolbox.getPanel("inspector");
|
||||
yield selectNode("#testid", inspector);
|
||||
let ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||
|
||||
// Disable the "font-size" property.
|
||||
let propEditor = ruleEditor.rule.textProps[0].editor;
|
||||
let onModification = view.once("ruleview-changed");
|
||||
propEditor.enable.click();
|
||||
yield onModification;
|
||||
|
||||
yield openStyleEditor();
|
||||
yield onEditorChange.promise;
|
||||
|
||||
let text = editor.sourceEditor.getText();
|
||||
is(text, expectedText, "style inspector changes are synced");
|
||||
});
|
||||
|
|
@ -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/ */
|
||||
"use strict";
|
||||
|
||||
// Test that changes in the style inspector are synchronized into the
|
||||
// style editor.
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTP + "sync.html";
|
||||
|
||||
const expectedText = `
|
||||
body {
|
||||
border-width: 15px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
#testid, span {
|
||||
font-size: 4em;
|
||||
}
|
||||
`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab(TESTCASE_URI);
|
||||
let { inspector, view } = yield openRuleView();
|
||||
yield selectNode("#testid", inspector);
|
||||
let ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||
|
||||
let editor = yield focusEditableField(view, ruleEditor.selectorText);
|
||||
editor.input.value = "#testid, span";
|
||||
let onRuleViewChanged = once(view, "ruleview-changed");
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
yield onRuleViewChanged;
|
||||
|
||||
let { ui } = yield openStyleEditor();
|
||||
|
||||
editor = yield ui.editors[0].getSourceEditor();
|
||||
let text = editor.sourceEditor.getText();
|
||||
is(text, expectedText, "selector edits are synced");
|
||||
});
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/* 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";
|
||||
|
||||
// Test that changes in the style editor are synchronized into the
|
||||
// style inspector.
|
||||
|
||||
const TEST_URI = `
|
||||
<style type='text/css'>
|
||||
</style>
|
||||
<div id='testid' class='testclass'>Styled Node</div>
|
||||
`;
|
||||
|
||||
const TESTCASE_CSS_SOURCE = "#testid { color: chartreuse; }";
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
||||
|
||||
let {inspector, view} = yield openRuleView();
|
||||
yield selectNode("#testid", inspector);
|
||||
|
||||
let { panel, ui } = yield openStyleEditor();
|
||||
|
||||
let editor = yield ui.editors[0].getSourceEditor();
|
||||
|
||||
let waitForRuleView = view.once("ruleview-refreshed");
|
||||
yield typeInEditor(editor, panel.panelWindow);
|
||||
yield waitForRuleView;
|
||||
|
||||
let value = getRuleViewPropertyValue(view, "#testid", "color");
|
||||
is(value, "chartreuse", "check that edits were synced to rule view");
|
||||
});
|
||||
|
||||
function typeInEditor(editor, panelWindow) {
|
||||
let deferred = defer();
|
||||
|
||||
waitForFocus(function () {
|
||||
for (let c of TESTCASE_CSS_SOURCE) {
|
||||
EventUtils.synthesizeKey(c, {}, panelWindow);
|
||||
}
|
||||
ok(editor.unsaved, "new editor has unsaved flag");
|
||||
|
||||
deferred.resolve();
|
||||
}, panelWindow);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/* 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 TESTCASE_URI = TEST_BASE_HTTPS + "simple.html";
|
||||
|
||||
const NEW_RULE = "body { background-color: purple; }";
|
||||
|
||||
add_task(function* () {
|
||||
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
|
||||
|
||||
is(ui.editors.length, 2, "correct number of editors");
|
||||
|
||||
let editor = ui.editors[0];
|
||||
yield openEditor(editor);
|
||||
|
||||
// Set text twice in a row
|
||||
let styleChanges = listenForStyleChange(editor.styleSheet);
|
||||
|
||||
editor.sourceEditor.setText(NEW_RULE);
|
||||
editor.sourceEditor.setText(NEW_RULE + " ");
|
||||
|
||||
yield styleChanges;
|
||||
|
||||
let rules = yield ContentTask.spawn(gBrowser.selectedBrowser, 0,
|
||||
function* (index) {
|
||||
let sheet = content.document.styleSheets[index];
|
||||
return [...sheet.cssRules].map(rule => rule.cssText);
|
||||
});
|
||||
|
||||
// Test that we removed the transition rule, but kept the rule we added
|
||||
is(rules.length, 1, "only one rule in stylesheet");
|
||||
is(rules[0], NEW_RULE, "stylesheet only contains rule we added");
|
||||
});
|
||||
|
||||
/* Helpers */
|
||||
|
||||
function openEditor(editor) {
|
||||
let link = editor.summary.querySelector(".stylesheet-name");
|
||||
link.click();
|
||||
|
||||
return editor.getSourceEditor();
|
||||
}
|
||||
|
||||
function listenForStyleChange(sheet) {
|
||||
let deferred = defer();
|
||||
sheet.on("style-applied", deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
22
devtools/client/styleeditor/test/browser_styleeditor_xul.js
Normal file
22
devtools/client/styleeditor/test/browser_styleeditor_xul.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that the style-editor initializes correctly for XUL windows.
|
||||
|
||||
"use strict";
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
const TEST_URL = TEST_BASE + "doc_xulpage.xul";
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(TEST_URL);
|
||||
let target = TargetFactory.forTab(tab);
|
||||
|
||||
let toolbox = yield gDevTools.showToolbox(target, "styleeditor");
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
|
||||
ok(panel,
|
||||
"The style-editor panel did initialize correctly for the XUL window");
|
||||
});
|
||||
403
devtools/client/styleeditor/test/doc_long.css
Normal file
403
devtools/client/styleeditor/test/doc_long.css
Normal file
|
|
@ -0,0 +1,403 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
div {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 7;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 8;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 12;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 13;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 14;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 16;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 17;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 18;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 19;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 21;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 22;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 23;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 24;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 25;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 26;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 27;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 28;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 29;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 30;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 31;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 32;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 33;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 34;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 35;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 36;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 37;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 38;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 39;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 40;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 41;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 42;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 43;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 44;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 45;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 46;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 47;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 48;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 49;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 51;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 52;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 53;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 54;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 55;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 56;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 57;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 58;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 59;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 60;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 61;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 62;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 63;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 64;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 65;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 66;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 67;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 68;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 69;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 70;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 71;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 72;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 73;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 74;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 75;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 76;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 77;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 78;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 79;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 80;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 81;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 82;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 83;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 84;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 85;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 86;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 87;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 88;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 89;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 90;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 91;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 92;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 93;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 94;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 95;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 96;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 97;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 98;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
div {
|
||||
z-index: 100;
|
||||
}
|
||||
16
devtools/client/styleeditor/test/doc_uncached.css
Normal file
16
devtools/client/styleeditor/test/doc_uncached.css
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* ☺ */
|
||||
|
||||
body {
|
||||
background: white;
|
||||
}
|
||||
|
||||
div {
|
||||
font-size: 4em;
|
||||
}
|
||||
|
||||
div > span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
10
devtools/client/styleeditor/test/doc_uncached.html
Normal file
10
devtools/client/styleeditor/test/doc_uncached.html
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>uncached testcase</title>
|
||||
<link rel="stylesheet" charset="UTF-8" type="text/css" media="screen" href="doc_uncached.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>uncached <span>testcase</span></div>
|
||||
</body>
|
||||
</html>
|
||||
7
devtools/client/styleeditor/test/doc_xulpage.xul
Normal file
7
devtools/client/styleeditor/test/doc_xulpage.xul
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="simple.css" type="text/css"?>
|
||||
<!DOCTYPE window>
|
||||
<window xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<label value="Simple XUL document" />
|
||||
</window>
|
||||
25
devtools/client/styleeditor/test/four.html
Normal file
25
devtools/client/styleeditor/test/four.html
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>four stylesheets</title>
|
||||
<link rel="stylesheet" type="text/css" media="scren" href="simple.css"/>
|
||||
<style type="text/css">
|
||||
div {
|
||||
font-size: 2em;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
span {
|
||||
font-size: 3em;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
p {
|
||||
font-size: 4em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>four <span>stylesheets</span></div>
|
||||
</body>
|
||||
</html>
|
||||
121
devtools/client/styleeditor/test/head.js
Normal file
121
devtools/client/styleeditor/test/head.js
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* All top-level definitions here are exports. */
|
||||
/* eslint no-unused-vars: [2, {"vars": "local"}] */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* import-globals-from ../../inspector/shared/test/head.js */
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/inspector/shared/test/head.js", this);
|
||||
|
||||
const TEST_BASE = "chrome://mochitests/content/browser/devtools/client/styleeditor/test/";
|
||||
const TEST_BASE_HTTP = "http://example.com/browser/devtools/client/styleeditor/test/";
|
||||
const TEST_BASE_HTTPS = "https://example.com/browser/devtools/client/styleeditor/test/";
|
||||
const TEST_HOST = "mochi.test:8888";
|
||||
|
||||
/**
|
||||
* Add a new test tab in the browser and load the given url.
|
||||
* @param {String} url The url to be loaded in the new tab
|
||||
* @param {Window} win The window to add the tab to (default: current window).
|
||||
* @return a promise that resolves to the tab object when the url is loaded
|
||||
*/
|
||||
var addTab = function (url, win) {
|
||||
info("Adding a new tab with URL: '" + url + "'");
|
||||
let def = defer();
|
||||
|
||||
let targetWindow = win || window;
|
||||
let targetBrowser = targetWindow.gBrowser;
|
||||
|
||||
let tab = targetBrowser.selectedTab = targetBrowser.addTab(url);
|
||||
BrowserTestUtils.browserLoaded(targetBrowser.selectedBrowser)
|
||||
.then(function () {
|
||||
info("URL '" + url + "' loading complete");
|
||||
def.resolve(tab);
|
||||
});
|
||||
|
||||
return def.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* Navigate the currently selected tab to a new URL and wait for it to load.
|
||||
* @param {String} url The url to be loaded in the current tab.
|
||||
* @return a promise that resolves when the page has fully loaded.
|
||||
*/
|
||||
var navigateTo = Task.async(function* (url) {
|
||||
info(`Navigating to ${url}`);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
|
||||
let navigating = defer();
|
||||
browser.addEventListener("load", function onload() {
|
||||
browser.removeEventListener("load", onload, true);
|
||||
navigating.resolve();
|
||||
}, true);
|
||||
|
||||
browser.loadURI(url);
|
||||
|
||||
yield navigating.promise;
|
||||
});
|
||||
|
||||
var navigateToAndWaitForStyleSheets = Task.async(function* (url, ui) {
|
||||
let onReset = ui.once("stylesheets-reset");
|
||||
yield navigateTo(url);
|
||||
yield onReset;
|
||||
});
|
||||
|
||||
var reloadPageAndWaitForStyleSheets = Task.async(function* (ui) {
|
||||
info("Reloading the page.");
|
||||
|
||||
let onReset = ui.once("stylesheets-reset");
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
yield ContentTask.spawn(browser, null, "() => content.location.reload()");
|
||||
yield onReset;
|
||||
});
|
||||
|
||||
/**
|
||||
* Open the style editor for the current tab.
|
||||
*/
|
||||
var openStyleEditor = Task.async(function* (tab) {
|
||||
if (!tab) {
|
||||
tab = gBrowser.selectedTab;
|
||||
}
|
||||
let target = TargetFactory.forTab(tab);
|
||||
let toolbox = yield gDevTools.showToolbox(target, "styleeditor");
|
||||
let panel = toolbox.getPanel("styleeditor");
|
||||
let ui = panel.UI;
|
||||
|
||||
return { toolbox, panel, ui };
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a new tab in specified window navigates it to the given URL and
|
||||
* opens style editor in it.
|
||||
*/
|
||||
var openStyleEditorForURL = Task.async(function* (url, win) {
|
||||
let tab = yield addTab(url, win);
|
||||
let result = yield openStyleEditor(tab);
|
||||
result.tab = tab;
|
||||
return result;
|
||||
});
|
||||
|
||||
/**
|
||||
* Send an async message to the frame script and get back the requested
|
||||
* computed style property.
|
||||
*
|
||||
* @param {String} selector
|
||||
* The selector used to obtain the element.
|
||||
* @param {String} pseudo
|
||||
* pseudo id to query, or null.
|
||||
* @param {String} name
|
||||
* name of the property.
|
||||
*/
|
||||
var getComputedStyleProperty = function* (args) {
|
||||
return yield ContentTask.spawn(gBrowser.selectedBrowser, args,
|
||||
function ({selector, pseudo, name}) {
|
||||
let element = content.document.querySelector(selector);
|
||||
let style = content.getComputedStyle(element, pseudo);
|
||||
return style.getPropertyValue(name);
|
||||
}
|
||||
);
|
||||
};
|
||||
10
devtools/client/styleeditor/test/import.css
vendored
Normal file
10
devtools/client/styleeditor/test/import.css
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
@import url(import2.css);
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
11
devtools/client/styleeditor/test/import.html
Normal file
11
devtools/client/styleeditor/test/import.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>import testcase</title>
|
||||
<link rel="stylesheet" charset="UTF-8" type="text/css" media="screen" href="simple.css"/>
|
||||
<link rel="stylesheet" charset="UTF-8" type="text/css" media="screen" href="import.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>import <span>testcase</span></div>
|
||||
</body>
|
||||
</html>
|
||||
10
devtools/client/styleeditor/test/import2.css
Normal file
10
devtools/client/styleeditor/test/import2.css
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
@import url(import.css);
|
||||
|
||||
p {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
19
devtools/client/styleeditor/test/inline-1.html
Normal file
19
devtools/client/styleeditor/test/inline-1.html
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Inline test page #1</title>
|
||||
<style type="text/css">
|
||||
.second {
|
||||
font-size:2em;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
.first {
|
||||
font-size:3em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="first">
|
||||
Inline test page #1
|
||||
</body>
|
||||
</html>
|
||||
19
devtools/client/styleeditor/test/inline-2.html
Normal file
19
devtools/client/styleeditor/test/inline-2.html
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Inline test page #2</title>
|
||||
<style type="text/css">
|
||||
.second {
|
||||
font-size:2em;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
.first {
|
||||
font-size:3em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="second">
|
||||
Inline test page #2
|
||||
</body>
|
||||
</html>
|
||||
29
devtools/client/styleeditor/test/longload.html
Normal file
29
devtools/client/styleeditor/test/longload.html
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Long load</title>
|
||||
<link rel="stylesheet" charset="UTF-8" type="text/css" media="screen" href="simple.css"/>
|
||||
<style type="text/css">
|
||||
body {
|
||||
background: white;
|
||||
}
|
||||
|
||||
div {
|
||||
font-size: 4em;
|
||||
}
|
||||
|
||||
div > span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
Time passes:
|
||||
<script type="application/javascript;version=1.8">
|
||||
"use strict";
|
||||
for (let i = 0; i < 5000; i++) {
|
||||
document.write("<br>...");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
12
devtools/client/styleeditor/test/media-rules-sourcemaps.html
Normal file
12
devtools/client/styleeditor/test/media-rules-sourcemaps.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" type="text/css" href="sourcemap-css/media-rules.css"
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
Testing style editor media sidebar with source maps
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
29
devtools/client/styleeditor/test/media-rules.css
Normal file
29
devtools/client/styleeditor/test/media-rules.css
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
@media not all {
|
||||
div {
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
|
||||
@media all {
|
||||
div {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: ghostwhite;
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
div {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 300px) and (max-height: 320px) {
|
||||
div {
|
||||
color: orange;
|
||||
}
|
||||
}
|
||||
13
devtools/client/styleeditor/test/media-rules.html
Normal file
13
devtools/client/styleeditor/test/media-rules.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="simple.css"/>
|
||||
<link rel="stylesheet" href="media-rules.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
Testing style editor media sidebar
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
5
devtools/client/styleeditor/test/media-small.css
Normal file
5
devtools/client/styleeditor/test/media-small.css
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/* this stylesheet applies when min-width<400px */
|
||||
body {
|
||||
background: red;
|
||||
}
|
||||
|
||||
11
devtools/client/styleeditor/test/media.html
Normal file
11
devtools/client/styleeditor/test/media.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="simple.css" media="screen,print"/>
|
||||
<link rel="stylesheet" type="text/css" href="media-small.css" media="screen and (min-width: 200px)"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>test for media labels</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
15
devtools/client/styleeditor/test/minified.html
Normal file
15
devtools/client/styleeditor/test/minified.html
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>minified testcase</title>
|
||||
<link rel="stylesheet" href="pretty.css"/>
|
||||
<style type="text/css">body { background: red; }
|
||||
div {
|
||||
font-size: 5em;
|
||||
color: red
|
||||
}</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>minified <span>testcase</span></div>
|
||||
</body>
|
||||
</html>
|
||||
11
devtools/client/styleeditor/test/missing.html
Normal file
11
devtools/client/styleeditor/test/missing.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>missing stylesheet testcase</title>
|
||||
<link rel="stylesheet" charset="utf-8" type="text/css" media="screen" href="missing-stylesheet.css"/>
|
||||
<link rel="stylesheet" charset="utf-8" type="text/css" media="screen" href="simple.css"/>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
5
devtools/client/styleeditor/test/nostyle.html
Normal file
5
devtools/client/styleeditor/test/nostyle.html
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<html>
|
||||
<div>
|
||||
Page with no stylesheets
|
||||
</div>
|
||||
</html>
|
||||
2
devtools/client/styleeditor/test/pretty.css
Normal file
2
devtools/client/styleeditor/test/pretty.css
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
body{background:white;}div{font-size:4em;color:red}span{color:green;}
|
||||
12
devtools/client/styleeditor/test/resources_inpage.jsi
Normal file
12
devtools/client/styleeditor/test/resources_inpage.jsi
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
// This script is used from within browser_styleeditor_cmd_edit.html
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
var pid = document.getElementById('pid');
|
||||
var h3 = document.createElement('h3');
|
||||
h3.id = 'h3id';
|
||||
h3.classList.add('h3class');
|
||||
h3.appendChild(document.createTextNode('h3'));
|
||||
h3.setAttribute('data-a1', 'h3');
|
||||
pid.parentNode.appendChild(h3);
|
||||
});
|
||||
11
devtools/client/styleeditor/test/resources_inpage1.css
Normal file
11
devtools/client/styleeditor/test/resources_inpage1.css
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
@charset "utf-8";
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#pid { border-top: 2px dotted #F00; }
|
||||
#divid { border-top: 2px dotted #00F; }
|
||||
#h4id { border-top: 2px dotted #0F0; }
|
||||
#h3id { border-top: 2px dotted #FF0; }
|
||||
11
devtools/client/styleeditor/test/resources_inpage2.css
Normal file
11
devtools/client/styleeditor/test/resources_inpage2.css
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
@charset "utf-8";
|
||||
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
*[data-a1=p] { border-left: 4px solid #F00; }
|
||||
*[data-a1=div] { border-left: 4px solid #00F; }
|
||||
*[data-a1=h4] { border-left: 4px solid #0F0; }
|
||||
*[data-a1=h3] { border-left: 4px solid #FF0; }
|
||||
9
devtools/client/styleeditor/test/simple.css
Normal file
9
devtools/client/styleeditor/test/simple.css
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* ☺ */
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
BIN
devtools/client/styleeditor/test/simple.css.gz
Normal file
BIN
devtools/client/styleeditor/test/simple.css.gz
Normal file
Binary file not shown.
4
devtools/client/styleeditor/test/simple.css.gz^headers^
Normal file
4
devtools/client/styleeditor/test/simple.css.gz^headers^
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
Vary: Accept-Encoding
|
||||
Content-Encoding: gzip
|
||||
Content-Type: text/css
|
||||
|
||||
23
devtools/client/styleeditor/test/simple.gz.html
Normal file
23
devtools/client/styleeditor/test/simple.gz.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>simple testcase</title>
|
||||
<link rel="stylesheet" type="text/css" media="scren" href="simple.css.gz"/>
|
||||
<style type="text/css">
|
||||
body {
|
||||
background: white;
|
||||
}
|
||||
|
||||
div {
|
||||
font-size: 4em;
|
||||
}
|
||||
|
||||
div > span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>simple <span>testcase</span></div>
|
||||
</body>
|
||||
</html>
|
||||
24
devtools/client/styleeditor/test/simple.html
Normal file
24
devtools/client/styleeditor/test/simple.html
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>simple testcase</title>
|
||||
<link rel="stylesheet" charset="UTF-8" type="text/css" media="screen" href="simple.css"/>
|
||||
<style type="text/css">
|
||||
body {
|
||||
background: white;
|
||||
}
|
||||
|
||||
div {
|
||||
font-size: 4em;
|
||||
}
|
||||
|
||||
div > span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>simple <span>testcase</span></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#header {
|
||||
color: #f06; }
|
||||
|
||||
/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiIiwic291cmNlcyI6WyJzYXNzL2NvbnRhaW5lZC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBO0VBQ0UsT0FISyIsInNvdXJjZXNDb250ZW50IjpbIiRwaW5rOiAjZjA2O1xuXG4jaGVhZGVyIHtcbiAgY29sb3I6ICRwaW5rO1xufSJdfQ==*/
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
@media screen and (max-width: 320px) {
|
||||
div {
|
||||
width: 100px; } }
|
||||
@media screen and (min-width: 1200px) {
|
||||
div {
|
||||
width: 400px; } }
|
||||
|
||||
/*# sourceMappingURL=media-rules.css.map */
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"version": 3,
|
||||
"mappings": "AAIE,oCAA4C;EAD9C,GAAI;IAEA,KAAK,EAAE,KAAK;AAEd,qCAA4C;EAJ9C,GAAI;IAKA,KAAK,EAAE,KAAK",
|
||||
"sources": ["../sourcemap-sass/media-rules.scss"],
|
||||
"file": "media-rules.css"
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
div {
|
||||
color: #ff0066; }
|
||||
|
||||
span {
|
||||
background-color: #EEE; }
|
||||
|
||||
/*# sourceMappingURL=sourcemaps.css.map */
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"version": 3,
|
||||
"mappings": "AAGA,GAAI;EACF,KAAK,EAHU,OAAI;;AAMrB,IAAK;EACH,gBAAgB,EAAE,IAAI",
|
||||
"sources": ["../sourcemap-sass/sourcemaps.scss"],
|
||||
"file": "sourcemaps.css"
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,7 @@
|
|||
div {
|
||||
color: #f06;
|
||||
}
|
||||
span {
|
||||
background-color: #eee;
|
||||
}
|
||||
/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3Qtc3R5bHVzLnN0eWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUE7RUFDRSxPQUFPLEtBQVA7O0FBRUY7RUFDRSxrQkFBa0IsS0FBbEIiLCJmaWxlIjoidGVzdC1zdHlsdXMuY3NzIiwic291cmNlc0NvbnRlbnQiOlsicGF1bHJvdWdldHBpbmsgPSAjZjA2O1xuXG5kaXZcbiAgY29sb3I6IHBhdWxyb3VnZXRwaW5rXG5cbnNwYW5cbiAgYmFja2dyb3VuZC1jb2xvcjogI0VFRVxuIl19 */
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
$break-small: 320px;
|
||||
$break-large: 1200px;
|
||||
|
||||
div {
|
||||
@media screen and (max-width: $break-small) {
|
||||
width: 100px;
|
||||
}
|
||||
@media screen and (min-width: $break-large) {
|
||||
width: 400px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
$paulrougetpink: #f06;
|
||||
|
||||
div {
|
||||
color: $paulrougetpink;
|
||||
}
|
||||
|
||||
span {
|
||||
background-color: #EEE;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
paulrougetpink = #f06;
|
||||
|
||||
div
|
||||
color: paulrougetpink
|
||||
|
||||
span
|
||||
background-color: #EEE
|
||||
17
devtools/client/styleeditor/test/sourcemaps-inline.html
Normal file
17
devtools/client/styleeditor/test/sourcemaps-inline.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>testcase for testing CSS source maps in inline style</title>
|
||||
<style type="text/css">body {
|
||||
background-color: black;
|
||||
}
|
||||
body > h1 {
|
||||
color: white;
|
||||
}
|
||||
/*# sourceMappingURL=data:application/json;base64,ewoidmVyc2lvbiI6IDMsCiJtYXBwaW5ncyI6ICJBQUFBLElBQUs7RUFDSCxnQkFBZ0IsRUFBRSxLQUFLO0VBQ3ZCLFNBQU87SUFDTCxLQUFLLEVBQUUsS0FBSyIsCiJzb3VyY2VzIjogWyJ0ZXN0LnNjc3MiXSwKInNvdXJjZXNDb250ZW50IjogWyJib2R5IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogYmxhY2s7XG4gICYgPiBoMSB7XG4gICAgY29sb3I6IHdoaXRlO1xuICB9XG59XG4iXSwKIm5hbWVzIjogW10sCiJmaWxlIjogInRlc3QuY3NzIgp9Cg== */</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Source maps testcase</div>
|
||||
</body>
|
||||
</html>
|
||||
11
devtools/client/styleeditor/test/sourcemaps-large.html
Normal file
11
devtools/client/styleeditor/test/sourcemaps-large.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>testcase for a loading error with CSS source maps</title>
|
||||
<link rel="stylesheet" type="text/css" href="sourcemap-css/test-bootstrap-scss.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>source maps <span>testcase</span> (see Bug 1128747)</div>
|
||||
</body>
|
||||
</html>
|
||||
11
devtools/client/styleeditor/test/sourcemaps-watching.html
Normal file
11
devtools/client/styleeditor/test/sourcemaps-watching.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>testcase for testing CSS source maps</title>
|
||||
<link rel="stylesheet" type="text/css" href="simple.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="sourcemap-css/sourcemaps.css?test=1"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>source maps <span>testcase</span></div>
|
||||
</body>
|
||||
</html>
|
||||
13
devtools/client/styleeditor/test/sourcemaps.html
Normal file
13
devtools/client/styleeditor/test/sourcemaps.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>testcase for testing CSS source maps</title>
|
||||
<link rel="stylesheet" type="text/css" href="simple.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="sourcemap-css/sourcemaps.css?test=1"/>
|
||||
<link rel="stylesheet" type="text/css" href="sourcemap-css/contained.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="sourcemap-css/test-stylus.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>source maps <span>testcase</span></div>
|
||||
</body>
|
||||
</html>
|
||||
20
devtools/client/styleeditor/test/sync.html
Normal file
20
devtools/client/styleeditor/test/sync.html
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>simple testcase</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
border-width: 15px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
#testid {
|
||||
font-size: 4em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="testid">simple testcase</div>
|
||||
</body>
|
||||
</html>
|
||||
3
devtools/client/styleeditor/test/test_private.css
Normal file
3
devtools/client/styleeditor/test/test_private.css
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background-color: red;
|
||||
}
|
||||
7
devtools/client/styleeditor/test/test_private.html
Normal file
7
devtools/client/styleeditor/test/test_private.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="test_private.css"></link>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
BIN
devtools/client/styleeditor/test/utf-16.css
Normal file
BIN
devtools/client/styleeditor/test/utf-16.css
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue