1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-01.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,298 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +/** 1.8 + * Make sure that the variables view knows how to edit getters and setters. 1.9 + */ 1.10 + 1.11 +const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; 1.12 + 1.13 +let gTab, gDebuggee, gPanel, gDebugger; 1.14 +let gL10N, gEditor, gVars, gWatch; 1.15 + 1.16 +function test() { 1.17 + // Debug test slaves are a bit slow at this test. 1.18 + requestLongerTimeout(2); 1.19 + 1.20 + initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { 1.21 + gTab = aTab; 1.22 + gDebuggee = aDebuggee; 1.23 + gPanel = aPanel; 1.24 + gDebugger = gPanel.panelWin; 1.25 + gL10N = gDebugger.L10N; 1.26 + gEditor = gDebugger.DebuggerView.editor; 1.27 + gVars = gDebugger.DebuggerView.Variables; 1.28 + gWatch = gDebugger.DebuggerView.WatchExpressions; 1.29 + 1.30 + gVars.switch = function() {}; 1.31 + gVars.delete = function() {}; 1.32 + 1.33 + waitForSourceAndCaretAndScopes(gPanel, ".html", 24) 1.34 + .then(() => addWatchExpressions()) 1.35 + .then(() => testEdit("set", "this._prop = value + ' BEER CAN'", { 1.36 + "myVar.prop": "xlerb BEER CAN", 1.37 + "myVar.prop + 42": "xlerb BEER CAN42", 1.38 + "myVar.prop = 'xlerb'": "xlerb" 1.39 + })) 1.40 + .then(() => testEdit("set", "{ this._prop = value + ' BEACON' }", { 1.41 + "myVar.prop": "xlerb BEACON", 1.42 + "myVar.prop + 42": "xlerb BEACON42", 1.43 + "myVar.prop = 'xlerb'": "xlerb" 1.44 + })) 1.45 + .then(() => testEdit("set", "{ this._prop = value + ' BEACON;'; }", { 1.46 + "myVar.prop": "xlerb BEACON;", 1.47 + "myVar.prop + 42": "xlerb BEACON;42", 1.48 + "myVar.prop = 'xlerb'": "xlerb" 1.49 + })) 1.50 + .then(() => testEdit("set", "{ return this._prop = value + ' BEACON;;'; }", { 1.51 + "myVar.prop": "xlerb BEACON;;", 1.52 + "myVar.prop + 42": "xlerb BEACON;;42", 1.53 + "myVar.prop = 'xlerb'": "xlerb" 1.54 + })) 1.55 + .then(() => testEdit("set", "function(value) { this._prop = value + ' BACON' }", { 1.56 + "myVar.prop": "xlerb BACON", 1.57 + "myVar.prop + 42": "xlerb BACON42", 1.58 + "myVar.prop = 'xlerb'": "xlerb" 1.59 + })) 1.60 + .then(() => testEdit("get", "'brelx BEER CAN'", { 1.61 + "myVar.prop": "brelx BEER CAN", 1.62 + "myVar.prop + 42": "brelx BEER CAN42", 1.63 + "myVar.prop = 'xlerb'": "xlerb" 1.64 + })) 1.65 + .then(() => testEdit("get", "{ 'brelx BEACON' }", { 1.66 + "myVar.prop": undefined, 1.67 + "myVar.prop + 42": NaN, 1.68 + "myVar.prop = 'xlerb'": "xlerb" 1.69 + })) 1.70 + .then(() => testEdit("get", "{ 'brelx BEACON;'; }", { 1.71 + "myVar.prop": undefined, 1.72 + "myVar.prop + 42": NaN, 1.73 + "myVar.prop = 'xlerb'": "xlerb" 1.74 + })) 1.75 + .then(() => testEdit("get", "{ return 'brelx BEACON;;'; }", { 1.76 + "myVar.prop": "brelx BEACON;;", 1.77 + "myVar.prop + 42": "brelx BEACON;;42", 1.78 + "myVar.prop = 'xlerb'": "xlerb" 1.79 + })) 1.80 + .then(() => testEdit("get", "function() { return 'brelx BACON'; }", { 1.81 + "myVar.prop": "brelx BACON", 1.82 + "myVar.prop + 42": "brelx BACON42", 1.83 + "myVar.prop = 'xlerb'": "xlerb" 1.84 + })) 1.85 + .then(() => testEdit("get", "bogus", { 1.86 + "myVar.prop": "ReferenceError: bogus is not defined", 1.87 + "myVar.prop + 42": "ReferenceError: bogus is not defined", 1.88 + "myVar.prop = 'xlerb'": "xlerb" 1.89 + })) 1.90 + .then(() => testEdit("set", "sugob", { 1.91 + "myVar.prop": "ReferenceError: bogus is not defined", 1.92 + "myVar.prop + 42": "ReferenceError: bogus is not defined", 1.93 + "myVar.prop = 'xlerb'": "ReferenceError: sugob is not defined" 1.94 + })) 1.95 + .then(() => testEdit("get", "", { 1.96 + "myVar.prop": undefined, 1.97 + "myVar.prop + 42": NaN, 1.98 + "myVar.prop = 'xlerb'": "ReferenceError: sugob is not defined" 1.99 + })) 1.100 + .then(() => testEdit("set", "", { 1.101 + "myVar.prop": "xlerb", 1.102 + "myVar.prop + 42": NaN, 1.103 + "myVar.prop = 'xlerb'": "xlerb" 1.104 + })) 1.105 + .then(() => deleteWatchExpression("myVar.prop = 'xlerb'")) 1.106 + .then(() => testEdit("self", "2507", { 1.107 + "myVar.prop": 2507, 1.108 + "myVar.prop + 42": 2549 1.109 + })) 1.110 + .then(() => deleteWatchExpression("myVar.prop + 42")) 1.111 + .then(() => testEdit("self", "0910", { 1.112 + "myVar.prop": 910 1.113 + })) 1.114 + .then(() => deleteLastWatchExpression("myVar.prop")) 1.115 + .then(() => testWatchExpressionsRemoved()) 1.116 + .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) 1.117 + .then(null, aError => { 1.118 + ok(false, "Got an error: " + aError.message + "\n" + aError.stack); 1.119 + }); 1.120 + 1.121 + EventUtils.sendMouseEvent({ type: "click" }, 1.122 + gDebuggee.document.querySelector("button"), 1.123 + gDebuggee); 1.124 + }); 1.125 +} 1.126 + 1.127 +function addWatchExpressions() { 1.128 + return promise.resolve(null) 1.129 + .then(() => { 1.130 + let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS); 1.131 + gWatch.addExpression("myVar.prop"); 1.132 + gEditor.focus(); 1.133 + return finished; 1.134 + }) 1.135 + .then(() => { 1.136 + let exprScope = gVars.getScopeAtIndex(0); 1.137 + ok(exprScope, 1.138 + "There should be a wach expressions scope in the variables view."); 1.139 + is(exprScope.name, gL10N.getStr("watchExpressionsScopeLabel"), 1.140 + "The scope's name should be marked as 'Watch Expressions'."); 1.141 + is(exprScope._store.size, 1, 1.142 + "There should be 1 evaluation available."); 1.143 + 1.144 + let w1 = exprScope.get("myVar.prop"); 1.145 + let w2 = exprScope.get("myVar.prop + 42"); 1.146 + let w3 = exprScope.get("myVar.prop = 'xlerb'"); 1.147 + 1.148 + ok(w1, "The first watch expression should be present in the scope."); 1.149 + ok(!w2, "The second watch expression should not be present in the scope."); 1.150 + ok(!w3, "The third watch expression should not be present in the scope."); 1.151 + 1.152 + is(w1.value, 42, "The first value is correct."); 1.153 + }) 1.154 + .then(() => { 1.155 + let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS); 1.156 + gWatch.addExpression("myVar.prop + 42"); 1.157 + gEditor.focus(); 1.158 + return finished; 1.159 + }) 1.160 + .then(() => { 1.161 + let exprScope = gVars.getScopeAtIndex(0); 1.162 + ok(exprScope, 1.163 + "There should be a wach expressions scope in the variables view."); 1.164 + is(exprScope.name, gL10N.getStr("watchExpressionsScopeLabel"), 1.165 + "The scope's name should be marked as 'Watch Expressions'."); 1.166 + is(exprScope._store.size, 2, 1.167 + "There should be 2 evaluations available."); 1.168 + 1.169 + let w1 = exprScope.get("myVar.prop"); 1.170 + let w2 = exprScope.get("myVar.prop + 42"); 1.171 + let w3 = exprScope.get("myVar.prop = 'xlerb'"); 1.172 + 1.173 + ok(w1, "The first watch expression should be present in the scope."); 1.174 + ok(w2, "The second watch expression should be present in the scope."); 1.175 + ok(!w3, "The third watch expression should not be present in the scope."); 1.176 + 1.177 + is(w1.value, "42", "The first expression value is correct."); 1.178 + is(w2.value, "84", "The second expression value is correct."); 1.179 + }) 1.180 + .then(() => { 1.181 + let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS); 1.182 + gWatch.addExpression("myVar.prop = 'xlerb'"); 1.183 + gEditor.focus(); 1.184 + return finished; 1.185 + }) 1.186 + .then(() => { 1.187 + let exprScope = gVars.getScopeAtIndex(0); 1.188 + ok(exprScope, 1.189 + "There should be a wach expressions scope in the variables view."); 1.190 + is(exprScope.name, gL10N.getStr("watchExpressionsScopeLabel"), 1.191 + "The scope's name should be marked as 'Watch Expressions'."); 1.192 + is(exprScope._store.size, 3, 1.193 + "There should be 3 evaluations available."); 1.194 + 1.195 + let w1 = exprScope.get("myVar.prop"); 1.196 + let w2 = exprScope.get("myVar.prop + 42"); 1.197 + let w3 = exprScope.get("myVar.prop = 'xlerb'"); 1.198 + 1.199 + ok(w1, "The first watch expression should be present in the scope."); 1.200 + ok(w2, "The second watch expression should be present in the scope."); 1.201 + ok(w3, "The third watch expression should be present in the scope."); 1.202 + 1.203 + is(w1.value, "xlerb", "The first expression value is correct."); 1.204 + is(w2.value, "xlerb42", "The second expression value is correct."); 1.205 + is(w3.value, "xlerb", "The third expression value is correct."); 1.206 + }); 1.207 +} 1.208 + 1.209 +function deleteWatchExpression(aString) { 1.210 + let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS); 1.211 + gWatch.deleteExpression({ name: aString }); 1.212 + return finished; 1.213 +} 1.214 + 1.215 +function deleteLastWatchExpression(aString) { 1.216 + let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES); 1.217 + gWatch.deleteExpression({ name: aString }); 1.218 + return finished; 1.219 +} 1.220 + 1.221 +function testEdit(aWhat, aString, aExpected) { 1.222 + let localScope = gVars.getScopeAtIndex(1); 1.223 + let myVar = localScope.get("myVar"); 1.224 + 1.225 + let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_PROPERTIES).then(() => { 1.226 + let propVar = myVar.get("prop"); 1.227 + let getterOrSetterOrVar = aWhat != "self" ? propVar.get(aWhat) : propVar; 1.228 + 1.229 + let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS).then(() => { 1.230 + let exprScope = gVars.getScopeAtIndex(0); 1.231 + ok(exprScope, 1.232 + "There should be a wach expressions scope in the variables view."); 1.233 + is(exprScope.name, gL10N.getStr("watchExpressionsScopeLabel"), 1.234 + "The scope's name should be marked as 'Watch Expressions'."); 1.235 + is(exprScope._store.size, Object.keys(aExpected).length, 1.236 + "There should be a certain number of evaluations available."); 1.237 + 1.238 + function testExpression(aExpression) { 1.239 + if (!aExpression) { 1.240 + return; 1.241 + } 1.242 + let value = aExpected[aExpression.name]; 1.243 + if (isNaN(value)) { 1.244 + ok(isNaN(aExpression.value), 1.245 + "The expression value is correct after the edit."); 1.246 + } else if (value == null) { 1.247 + is(aExpression.value.type, value + "", 1.248 + "The expression value is correct after the edit."); 1.249 + } else { 1.250 + is(aExpression.value, value, 1.251 + "The expression value is correct after the edit."); 1.252 + } 1.253 + } 1.254 + 1.255 + testExpression(exprScope.get(Object.keys(aExpected)[0])); 1.256 + testExpression(exprScope.get(Object.keys(aExpected)[1])); 1.257 + testExpression(exprScope.get(Object.keys(aExpected)[2])); 1.258 + }); 1.259 + 1.260 + let editTarget = getterOrSetterOrVar.target; 1.261 + 1.262 + // Allow the target variable to get painted, so that clicking on 1.263 + // its value would scroll the new textbox node into view. 1.264 + executeSoon(() => { 1.265 + let varValue = editTarget.querySelector(".title > .value"); 1.266 + EventUtils.sendMouseEvent({ type: "mousedown" }, varValue, gDebugger); 1.267 + 1.268 + let varInput = editTarget.querySelector(".title > .element-value-input"); 1.269 + setText(varInput, aString); 1.270 + EventUtils.sendKey("RETURN", gDebugger); 1.271 + }); 1.272 + 1.273 + return finished; 1.274 + }); 1.275 + 1.276 + myVar.expand(); 1.277 + gVars.clearHierarchy(); 1.278 + 1.279 + return finished; 1.280 +} 1.281 + 1.282 +function testWatchExpressionsRemoved() { 1.283 + let scope = gVars.getScopeAtIndex(0); 1.284 + ok(scope, 1.285 + "There should be a local scope in the variables view."); 1.286 + isnot(scope.name, gL10N.getStr("watchExpressionsScopeLabel"), 1.287 + "The scope's name should not be marked as 'Watch Expressions'."); 1.288 + isnot(scope._store.size, 0, 1.289 + "There should be some variables available."); 1.290 +} 1.291 + 1.292 +registerCleanupFunction(function() { 1.293 + gTab = null; 1.294 + gDebuggee = null; 1.295 + gPanel = null; 1.296 + gDebugger = null; 1.297 + gL10N = null; 1.298 + gEditor = null; 1.299 + gVars = null; 1.300 + gWatch = null; 1.301 +});