Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* vim: set ts=2 et sw=2 tw=80: */
2 /* Any copyright is dedicated to the Public Domain.
3 http://creativecommons.org/publicdomain/zero/1.0/ */
5 const TESTCASE_URI = TEST_BASE + "autocomplete.html";
6 const MAX_SUGGESTIONS = 15;
8 // Pref which decides if CSS autocompletion is enabled in Style Editor or not.
9 const AUTOCOMPLETION_PREF = "devtools.styleeditor.autocompletion-enabled";
11 const {CSSProperties, CSSValues} = getCSSKeywords();
13 // Test cases to test that autocompletion works correctly when enabled.
14 // Format:
15 // [
16 // key,
17 // {
18 // total: Number of suggestions in the popup (-1 if popup is closed),
19 // current: Index of selected suggestion,
20 // inserted: 1 to check whether the selected suggestion is inserted into the editor or not,
21 // entered: 1 if the suggestion is inserted and finalized
22 // }
23 // ]
24 let TEST_CASES = [
25 ['VK_RIGHT'],
26 ['VK_RIGHT'],
27 ['VK_RIGHT'],
28 ['VK_RIGHT'],
29 ['Ctrl+Space', {total: 1, current: 0}],
30 ['VK_LEFT'],
31 ['VK_RIGHT'],
32 ['VK_DOWN'],
33 ['VK_RIGHT'],
34 ['VK_RIGHT'],
35 ['VK_RIGHT'],
36 ['Ctrl+Space', { total: getSuggestionNumberFor("font"), current: 0}],
37 ['VK_END'],
38 ['VK_RETURN'],
39 ['b', {total: getSuggestionNumberFor("b"), current: 0}],
40 ['a', {total: getSuggestionNumberFor("ba"), current: 0}],
41 ['VK_DOWN', {total: getSuggestionNumberFor("ba"), current: 0, inserted: 1}],
42 ['VK_TAB', {total: getSuggestionNumberFor("ba"), current: 1, inserted: 1}],
43 ['VK_RETURN', {current: 1, inserted: 1, entered: 1}],
44 ['b', {total: getSuggestionNumberFor("background", "b"), current: 0}],
45 ['l', {total: getSuggestionNumberFor("background", "bl"), current: 0}],
46 ['VK_TAB', {total: getSuggestionNumberFor("background", "bl"), current: 0, inserted: 1}],
47 ['VK_DOWN', {total: getSuggestionNumberFor("background", "bl"), current: 1, inserted: 1}],
48 ['VK_UP', {total: getSuggestionNumberFor("background", "bl"), current: 0, inserted: 1}],
49 ['VK_TAB', {total: getSuggestionNumberFor("background", "bl"), current: 1, inserted: 1}],
50 ['VK_TAB', {total: getSuggestionNumberFor("background", "bl"), current: 2, inserted: 1}],
51 [';'],
52 ['VK_RETURN'],
53 ['c', {total: getSuggestionNumberFor("c"), current: 0}],
54 ['o', {total: getSuggestionNumberFor("co"), current: 0}],
55 ['VK_RETURN', {current: 0, inserted: 1}],
56 ['r', {total: getSuggestionNumberFor("color", "r"), current: 0}],
57 ['VK_RETURN', {current: 0, inserted: 1}],
58 [';'],
59 ['VK_LEFT'],
60 ['VK_RIGHT'],
61 ['VK_DOWN'],
62 ['VK_RETURN'],
63 ['b', {total: 2, current: 0}],
64 ['u', {total: 1, current: 0}],
65 ['VK_RETURN', {current: 0, inserted: 1}],
66 ['{'],
67 ['VK_HOME'],
68 ['VK_DOWN'],
69 ['VK_DOWN'],
70 ['VK_RIGHT'],
71 ['VK_RIGHT'],
72 ['VK_RIGHT'],
73 ['VK_RIGHT'],
74 ['VK_RIGHT'],
75 ['VK_RIGHT'],
76 ['VK_RIGHT'],
77 ['VK_RIGHT'],
78 ['VK_RIGHT'],
79 ['VK_RIGHT'],
80 ['Ctrl+Space', {total: 1, current: 0}],
81 ];
83 let gEditor;
84 let gPopup;
85 let index = 0;
87 function test()
88 {
89 waitForExplicitFinish();
91 addTabAndOpenStyleEditors(1, testEditorAdded);
93 content.location = TESTCASE_URI;
94 }
96 function testEditorAdded(panel) {
97 info("Editor added, getting the source editor and starting tests");
98 panel.UI.editors[0].getSourceEditor().then(editor => {
99 info("source editor found, starting tests.");
100 gEditor = editor.sourceEditor;
101 gPopup = gEditor.getAutocompletionPopup();
102 waitForFocus(testState, gPanelWindow);
103 });
104 }
106 function testState() {
107 if (index == TEST_CASES.length) {
108 testAutocompletionDisabled();
109 return;
110 }
112 let [key, details] = TEST_CASES[index];
113 let entered;
114 if (details) {
115 entered = details.entered;
116 }
117 let mods = {};
119 info("pressing key " + key + " to get result: " +
120 JSON.stringify(TEST_CASES[index]) + " for index " + index);
122 let evt = "after-suggest";
124 if (key == 'Ctrl+Space') {
125 key = " ";
126 mods.accelKey = true;
127 }
128 else if (key == "VK_RETURN" && entered) {
129 evt = "popup-hidden";
130 }
131 else if (/(left|right|return|home|end)/ig.test(key) ||
132 (key == "VK_DOWN" && !gPopup.isOpen)) {
133 evt = "cursorActivity";
134 }
135 else if (key == "VK_TAB" || key == "VK_UP" || key == "VK_DOWN") {
136 evt = "suggestion-entered";
137 }
139 gEditor.once(evt, checkState);
140 EventUtils.synthesizeKey(key, mods, gPanelWindow);
141 }
143 function checkState() {
144 executeSoon(() => {
145 let [key, details] = TEST_CASES[index];
146 details = details || {};
147 let {total, current, inserted} = details;
149 if (total != undefined) {
150 ok(gPopup.isOpen, "Popup is open for index " + index);
151 is(total, gPopup.itemCount,
152 "Correct total suggestions for index " + index);
153 is(current, gPopup.selectedIndex,
154 "Correct index is selected for index " + index);
155 if (inserted) {
156 let { preLabel, label, text } = gPopup.getItemAtIndex(current);
157 let { line, ch } = gEditor.getCursor();
158 let lineText = gEditor.getText(line);
159 is(lineText.substring(ch - text.length, ch), text,
160 "Current suggestion from the popup is inserted into the editor.");
161 }
162 }
163 else {
164 ok(!gPopup.isOpen, "Popup is closed for index " + index);
165 if (inserted) {
166 let { preLabel, label, text } = gPopup.getItemAtIndex(current);
167 let { line, ch } = gEditor.getCursor();
168 let lineText = gEditor.getText(line);
169 is(lineText.substring(ch - text.length, ch), text,
170 "Current suggestion from the popup is inserted into the editor.");
171 }
172 }
173 index++;
174 testState();
175 });
176 }
178 function testAutocompletionDisabled() {
179 gBrowser.removeCurrentTab();
181 index = 0;
182 info("Starting test to check if autocompletion is disabled correctly.")
183 Services.prefs.setBoolPref(AUTOCOMPLETION_PREF, false);
185 addTabAndOpenStyleEditors(1, testEditorAddedDisabled);
187 content.location = TESTCASE_URI;
188 }
190 function testEditorAddedDisabled(panel) {
191 info("Editor added, getting the source editor and starting tests");
192 panel.UI.editors[0].getSourceEditor().then(editor => {
193 ok(!editor.sourceEditor.getAutocompletionPopup,
194 "Autocompletion popup does not exist");
195 cleanup();
196 });
197 }
199 function cleanup() {
200 Services.prefs.clearUserPref(AUTOCOMPLETION_PREF);
201 gEditor = null;
202 gPopup = null;
203 finish();
204 }
206 /**
207 * Returns a list of all property names and a map of property name vs possible
208 * CSS values provided by the Gecko engine.
209 *
210 * @return {Object} An object with following properties:
211 * - CSSProperties {Array} Array of string containing all the possible
212 * CSS property names.
213 * - CSSValues {Object|Map} A map where key is the property name and
214 * value is an array of string containing all the possible
215 * CSS values the property can have.
216 */
217 function getCSSKeywords() {
218 let domUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
219 .getService(Ci.inIDOMUtils);
220 let props = {};
221 let propNames = domUtils.getCSSPropertyNames(domUtils.INCLUDE_ALIASES);
222 propNames.forEach(prop => {
223 props[prop] = domUtils.getCSSValuesForProperty(prop).sort();
224 });
225 return {
226 CSSValues: props,
227 CSSProperties: propNames.sort()
228 };
229 }
231 /**
232 * Returns the number of expected suggestions for the given property and value.
233 * If the value is not null, returns the number of values starting with `value`.
234 * Returns the number of properties starting with `property` otherwise.
235 */
236 function getSuggestionNumberFor(property, value) {
237 if (value == null) {
238 return CSSProperties.filter(prop => prop.startsWith(property))
239 .slice(0, MAX_SUGGESTIONS).length;
240 }
241 return CSSValues[property].filter(val => val.startsWith(value))
242 .slice(0, MAX_SUGGESTIONS).length;
243 }