From 8e3039ce734e2ed8137373c56894926b317b7038 Mon Sep 17 00:00:00 2001 From: Jason San Jose Date: Thu, 19 Jul 2012 15:36:19 -0700 Subject: [PATCH 1/5] Prevent extensions from loading in test windows. Separate extension unit tests as a suite. Fix broken perf tests. --- src/brackets.js | 17 +++- .../default/JavaScriptQuickEdit/unittests.js | 2 +- src/utils/PerfUtils.js | 15 +++ test/PerformanceTestSuite.js | 2 +- test/SpecRunner.html | 3 +- test/SpecRunner.js | 85 +++++++++++------ test/perf/Performance-test.js | 17 ++-- test/perf/PerformanceReporter.js | 14 ++- test/spec/SpecRunnerUtils.js | 93 ++++++++++++------- 9 files changed, 166 insertions(+), 82 deletions(-) diff --git a/src/brackets.js b/src/brackets.js index 37115befeb5..d2809179696 100644 --- a/src/brackets.js +++ b/src/brackets.js @@ -81,9 +81,16 @@ define(function (require, exports, module) { Async = require("utils/Async"); // Local variables - var bracketsReady = false, - bracketsReadyHandlers = []; - + var bracketsReady = false, + bracketsReadyHandlers = [], + paramMap = [], + params = window.document.location.search.substring(1).split('&'); + + params.forEach(function (param) { + var p = param.split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + }); + //Load modules that self-register and just need to get included in the main project require("document/ChangedDocumentTracker"); require("editor/EditorCommandHandlers"); @@ -175,7 +182,9 @@ define(function (require, exports, module) { // TODO: (issue 1029) Add timeout to main extension loading promise, so that we always call this function // Making this fix will fix a warning (search for issue 1029) related to the brackets 'ready' event. function _initExtensions() { - return Async.doInParallel(["default", "user"], function (item) { + var paths = paramMap.extensions || "default,user"; + + return Async.doInParallel(paths.split(","), function (item) { return ExtensionLoader.loadAllExtensionsInNativeDirectory( FileUtils.getNativeBracketsDirectoryPath() + "/extensions/" + item, "extensions/" + item diff --git a/src/extensions/default/JavaScriptQuickEdit/unittests.js b/src/extensions/default/JavaScriptQuickEdit/unittests.js index cfd30658fa3..89212c7c496 100644 --- a/src/extensions/default/JavaScriptQuickEdit/unittests.js +++ b/src/extensions/default/JavaScriptQuickEdit/unittests.js @@ -279,7 +279,7 @@ define(function (require, exports, module) { describe("Performance suite", function () { - this.performance = true; + this.category = "performance"; var testPath = SpecRunnerUtils.getTestPath("/../../../brackets-scenario/jquery-ui/"); diff --git a/src/utils/PerfUtils.js b/src/utils/PerfUtils.js index cd6684d3bb9..203400507d1 100644 --- a/src/utils/PerfUtils.js +++ b/src/utils/PerfUtils.js @@ -316,6 +316,20 @@ define(function (require, exports, module) { return perfData[toMeasurementId(name)]; } + function searchData(regExp) { + var keys = Object.keys(perfData).filter(function (key) { + return regExp.test(key); + }); + + var datas = []; + + keys.forEach(function (key) { + datas.push(perfData[key]); + }); + + return datas; + } + /** * Clear all logs including metric data and active tests. */ @@ -336,6 +350,7 @@ define(function (require, exports, module) { exports.isActive = isActive; exports.markStart = markStart; exports.getData = getData; + exports.searchData = searchData; exports.updateMeasurement = updateMeasurement; exports.getDelimitedPerfData = getDelimitedPerfData; exports.createPerfMeasurement = createPerfMeasurement; diff --git a/test/PerformanceTestSuite.js b/test/PerformanceTestSuite.js index addeefd4c52..95c1430ad60 100644 --- a/test/PerformanceTestSuite.js +++ b/test/PerformanceTestSuite.js @@ -26,6 +26,6 @@ define(function (require, exports, module) { 'use strict'; - // Each suite or spec must have this.performance = true to be filtered properly + // Each suite or spec must have this.category === "performance" to be filtered properly require("perf/Performance-test"); }); \ No newline at end of file diff --git a/test/SpecRunner.html b/test/SpecRunner.html index 6ba50016c7c..d632d8f9762 100644 --- a/test/SpecRunner.html +++ b/test/SpecRunner.html @@ -32,8 +32,6 @@ - - @@ -61,6 +59,7 @@ diff --git a/test/SpecRunner.js b/test/SpecRunner.js index 8d0e47e2887..27b91b1b8e4 100644 --- a/test/SpecRunner.js +++ b/test/SpecRunner.js @@ -70,13 +70,26 @@ define(function (require, exports, module) { return paramMap; } - function _loadExtensionTests() { - var bracketsPath = FileUtils.getNativeBracketsDirectoryPath(); + function _loadExtensionTests(suite) { + // augment jasmine to identify extension unit tests + var addSuite = jasmine.Runner.prototype.addSuite; + jasmine.Runner.prototype.addSuite = function (suite) { + suite.category = "extension"; + addSuite.call(this, suite); + }; + + var bracketsPath = FileUtils.getNativeBracketsDirectoryPath(), + paths = ["default"]; + + // load user extensions only when running the extension test suite + if (suite === "ExtensionTestSuite") { + paths.push("user"); + } // This returns path to test folder, so convert to src bracketsPath = bracketsPath.replace("brackets/test", "brackets/src"); - return Async.doInParallel(["default", "user"], function (dir) { + return Async.doInParallel(paths, function (dir) { return ExtensionLoader.testAllExtensionsInNativeDirectory( bracketsPath + "/extensions/" + dir, "extensions/" + dir @@ -123,8 +136,47 @@ define(function (require, exports, module) { // Note: we change the name to "getModule" because this won't do exactly the same thing as 'require' in AMD-wrapped // modules. The extension will only be able to load modules that have already been loaded once. brackets.getModule = require; + + suite = getParamMap().suite || localStorage.getItem("SpecRunner.suite") || "UnitTestSuite"; + + // Create a top-level filter to show/hide performance and extensions tests + var isPerfSuite = (suite === "PerformanceTestSuite"), + isExtSuite = (suite === "ExtensionTestSuite"); + + var topLevelFilter = function (spec) { + if (!isPerfSuite && !isExtSuite) { + return !spec.category; + } + + var category = (isPerfSuite) ? "performance" : "extension"; + + if (spec.category === category) { + return true; + } + + var suite = spec.suite; + + while (suite) { + if (suite.category === category) { + return true; + } + + suite = suite.parentSuite; + } + + return false; + }; - _loadExtensionTests().done(function () { + /* + * TODO (jason-sanjose): extension unit tests should only load the + * extension and the extensions dependencies. We should not load + * unrelated extensions. Currently, this solution is all or nothing. + */ + + // configure spawned test windows to load extensions + SpecRunnerUtils.setLoadExtensionsInTestWindow(isExtSuite); + + _loadExtensionTests(suite).done(function () { var jasmineEnv = jasmine.getEnv(); // Initiailize unit test preferences for each spec @@ -140,35 +192,14 @@ define(function (require, exports, module) { jasmineEnv.updateInterval = 1000; - suite = getParamMap().suite || localStorage.getItem("SpecRunner.suite") || "UnitTestSuite"; - - // Create a top-level filter to show/hide performance tests - var isPerfSuite = (suite === "PerformanceTestSuite"), - performanceFilter = function (spec) { - if (spec.performance === true) { - return isPerfSuite; - } - - var suite = spec.suite; - - while (suite) { - if (suite.performance === true) { - return isPerfSuite; - } - - suite = suite.parentSuite; - } - - return !isPerfSuite; - }; - - jasmineEnv.addReporter(new jasmine.BootstrapReporter(document, performanceFilter)); + jasmineEnv.addReporter(new jasmine.BootstrapReporter(document, topLevelFilter)); // add performance reporting if (isPerfSuite) { jasmineEnv.addReporter(new PerformanceReporter()); } + // remember the suite for the next unit test window launch localStorage.setItem("SpecRunner.suite", suite); $(window.document).ready(_documentReadyHandler); diff --git a/test/perf/Performance-test.js b/test/perf/Performance-test.js index 3e4052830f3..fdf1b4af419 100644 --- a/test/perf/Performance-test.js +++ b/test/perf/Performance-test.js @@ -22,7 +22,7 @@ */ /*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */ -/*global define, describe, beforeEach, afterEach, it, runs, waitsFor, expect, brackets */ +/*global define, describe, beforeEach, afterEach, it, runs, waitsFor, waitsForDone, expect, brackets */ // TODO: Eventually we should have a brackets performance test suite that is separate from the unit tests @@ -43,7 +43,7 @@ define(function (require, exports, module) { describe("Performance Tests", function () { - this.performance = true; + this.category = "performance"; // Note: this tests assumes that the "brackets-scenario" repo is in the same folder // as the "brackets-app" @@ -54,19 +54,14 @@ define(function (require, exports, module) { testWindow; function openFile(path) { - var didOpen = false, gotError = false; - + var fullPath = testPath + path; runs(function () { - CommandManager.execute(Commands.FILE_OPEN, {fullPath: testPath + path}) - .done(function () { - didOpen = true; - }) - .fail(function () { gotError = true; }); + var promise = CommandManager.execute(Commands.FILE_OPEN, {fullPath: fullPath}); + waitsForDone(promise); }); - waitsFor(function () { return didOpen && !gotError; }, 1000); runs(function () { - PerformanceReporter.logTestWindow(PerfUtils.OPEN_FILE, path); + PerformanceReporter.logTestWindow(/Open File:\t,*/, path); PerformanceReporter.clearTestWindow(); }); } diff --git a/test/perf/PerformanceReporter.js b/test/perf/PerformanceReporter.js index 9dc93068734..27d0a3d8192 100644 --- a/test/perf/PerformanceReporter.js +++ b/test/perf/PerformanceReporter.js @@ -38,16 +38,22 @@ define(function (require, exports, module) { } function _logTestWindowMeasurement(measureInfo) { - var value = currentPerfUtils.getData(measureInfo.measure.id), - printName = measureInfo.measure.name, + var value, + printName = measureInfo.measure.name || measureInfo.name, record = {}; + if (measureInfo.measure instanceof RegExp) { + value = currentPerfUtils.searchData(measureInfo.measure); + } else { + value = currentPerfUtils.getData(measureInfo.measure.id); + } + if (value === undefined) { value = "(None)"; } - if (measureInfo.name) { - printName = printName + " - " + measureInfo.name; + if (measureInfo.measure.name && measureInfo.name) { + printName = measureInfo.measure.name + " - " + measureInfo.name; } if (measureInfo.operation === "sum") { diff --git a/test/spec/SpecRunnerUtils.js b/test/spec/SpecRunnerUtils.js index b6fb8696638..d6b09c46f7e 100644 --- a/test/spec/SpecRunnerUtils.js +++ b/test/spec/SpecRunnerUtils.js @@ -37,7 +37,8 @@ define(function (require, exports, module) { OPEN_TAG = "{{", CLOSE_TAG = "}}", RE_MARKER = /[^\\]?\{\{(\d+)[^\\]?\}\}/g, - testWindow; + _testWindow, + _doLoadExtensions; function getTestRoot() { // /path/to/brackets/test/SpecRunner.html @@ -59,6 +60,23 @@ define(function (require, exports, module) { return path.join("/"); } + function Params() { + this.params = []; + } + + Params.prototype.push = function (name, value) { + this.params.push({name: name, value: value}); + }; + + Params.prototype.toString = function () { + var strs = []; + + this.params.forEach(function (param) { + strs.push(encodeURIComponent(param.name) + "=" + encodeURIComponent(param.value)); + }); + + return strs.join("&"); + }; /** * Utility for tests that wait on a Promise to complete. Placed in the global namespace so it can be used @@ -128,24 +146,30 @@ define(function (require, exports, module) { testWindowY = window.screen.availHeight - testWindowHt, optionsStr = "left=" + testWindowX + ",top=" + testWindowY + ",width=" + testWindowWid + ",height=" + testWindowHt; - testWindow = window.open(getBracketsSourceRoot() + "/index.html", "_blank", optionsStr); - testWindow.executeCommand = function executeCommand(cmd, args) { - return testWindow.brackets.test.CommandManager.execute(cmd, args); + var params = new Params(); + + // setup extension loading in the test window + params.push("extensions", _doLoadExtensions ? "default,user" : "default"); + + _testWindow = window.open(getBracketsSourceRoot() + "/index.html?" + params.toString(), "_blank", optionsStr); + + _testWindow.executeCommand = function executeCommand(cmd, args) { + return _testWindow.brackets.test.CommandManager.execute(cmd, args); }; }); // FIXME (issue #249): Need an event or something a little more reliable... waitsFor( function isBracketsDoneLoading() { - return testWindow.brackets && testWindow.brackets.test && testWindow.brackets.test.doneLoading; + return _testWindow.brackets && _testWindow.brackets.test && _testWindow.brackets.test.doneLoading; }, 10000 ); runs(function () { // callback allows specs to query the testWindow before they run - callback.call(spec, testWindow); + callback.call(spec, _testWindow); }); } @@ -156,7 +180,7 @@ define(function (require, exports, module) { runs(function () { //we need to mark the documents as not dirty before we close //or the window will stay open prompting to save - var openDocs = testWindow.brackets.test.DocumentManager.getAllOpenDocuments(); + var openDocs = _testWindow.brackets.test.DocumentManager.getAllOpenDocuments(); openDocs.forEach(function resetDoc(doc) { if (doc.isDirty) { //just refresh it back to it's current text. This will mark it @@ -164,7 +188,7 @@ define(function (require, exports, module) { doc.refreshText(doc.getText(), doc.diskTimestamp); } }); - testWindow.close(); + _testWindow.close(); }); } @@ -178,7 +202,7 @@ define(function (require, exports, module) { */ function clickDialogButton(buttonId) { // Make sure there's one and only one dialog open - var $dlg = testWindow.$(".modal.instance"), + var $dlg = _testWindow.$(".modal.instance"), promise = $dlg.data("promise"); expect($dlg.length).toBe(1); @@ -200,7 +224,7 @@ define(function (require, exports, module) { runs(function () { // begin loading project path - var result = testWindow.brackets.test.ProjectManager.openProject(path); + var result = _testWindow.brackets.test.ProjectManager.openProject(path); result.done(function () { isReady = true; }); @@ -268,7 +292,7 @@ define(function (require, exports, module) { * @return {!Array.|string} Absolute file path(s) */ function makeAbsolute(paths) { - var fullPath = testWindow.brackets.test.ProjectManager.getProjectRoot().fullPath; + var fullPath = _testWindow.brackets.test.ProjectManager.getProjectRoot().fullPath; function prefixProjectPath(path) { if (path.indexOf(fullPath) === 0) { @@ -292,7 +316,7 @@ define(function (require, exports, module) { * @return {!Array.|string} Relative file path(s) */ function makeRelative(paths) { - var fullPath = testWindow.brackets.test.ProjectManager.getProjectRoot().fullPath, + var fullPath = _testWindow.brackets.test.ProjectManager.getProjectRoot().fullPath, fullPathLength = fullPath.length; function removeProjectPath(path) { @@ -351,7 +375,7 @@ define(function (require, exports, module) { fullpaths = makeArray(makeAbsolute(paths)), keys = makeArray(makeRelative(paths)), docs = {}, - FileViewController = testWindow.brackets.test.FileViewController; + FileViewController = _testWindow.brackets.test.FileViewController; Async.doSequentially(fullpaths, function (path, i) { var one = new $.Deferred(); @@ -456,7 +480,7 @@ define(function (require, exports, module) { function toggleQuickEditAtOffset(editor, offset) { editor.setCursorPos(offset.line, offset.ch); - return testWindow.executeCommand(Commands.TOGGLE_QUICK_EDIT); + return _testWindow.executeCommand(Commands.TOGGLE_QUICK_EDIT); } /** @@ -523,26 +547,31 @@ define(function (require, exports, module) { } function getTestWindow() { - return testWindow; + return _testWindow; + } + + function setLoadExtensionsInTestWindow(doLoadExtensions) { + _doLoadExtensions = doLoadExtensions; } exports.TEST_PREFERENCES_KEY = TEST_PREFERENCES_KEY; - exports.getTestRoot = getTestRoot; - exports.getTestPath = getTestPath; - exports.getBracketsSourceRoot = getBracketsSourceRoot; - exports.makeAbsolute = makeAbsolute; - exports.createMockDocument = createMockDocument; - exports.createTestWindowAndRun = createTestWindowAndRun; - exports.closeTestWindow = closeTestWindow; - exports.clickDialogButton = clickDialogButton; - exports.loadProjectInTestWindow = loadProjectInTestWindow; - exports.openProjectFiles = openProjectFiles; - exports.toggleQuickEditAtOffset = toggleQuickEditAtOffset; - exports.saveFilesWithOffsets = saveFilesWithOffsets; - exports.saveFilesWithoutOffsets = saveFilesWithoutOffsets; - exports.saveFileWithoutOffsets = saveFileWithoutOffsets; - exports.deleteFile = deleteFile; - exports.getTestWindow = getTestWindow; - exports.simulateKeyEvent = simulateKeyEvent; + exports.getTestRoot = getTestRoot; + exports.getTestPath = getTestPath; + exports.getBracketsSourceRoot = getBracketsSourceRoot; + exports.makeAbsolute = makeAbsolute; + exports.createMockDocument = createMockDocument; + exports.createTestWindowAndRun = createTestWindowAndRun; + exports.closeTestWindow = closeTestWindow; + exports.clickDialogButton = clickDialogButton; + exports.loadProjectInTestWindow = loadProjectInTestWindow; + exports.openProjectFiles = openProjectFiles; + exports.toggleQuickEditAtOffset = toggleQuickEditAtOffset; + exports.saveFilesWithOffsets = saveFilesWithOffsets; + exports.saveFilesWithoutOffsets = saveFilesWithoutOffsets; + exports.saveFileWithoutOffsets = saveFileWithoutOffsets; + exports.deleteFile = deleteFile; + exports.getTestWindow = getTestWindow; + exports.simulateKeyEvent = simulateKeyEvent; + exports.setLoadExtensionsInTestWindow = setLoadExtensionsInTestWindow; }); From e9e6d31d799f2fb7fd9f82e0bc2667cdeaaa33fd Mon Sep 17 00:00:00 2001 From: Jason San Jose Date: Thu, 19 Jul 2012 17:59:17 -0700 Subject: [PATCH 2/5] Refactor url param usage to use new Params class. Additional code review comments. --- src/brackets.js | 15 ++++---- src/utils/Params.js | 67 ++++++++++++++++++++++++++++++++++++ test/BootstrapReporter.js | 25 ++++++-------- test/SpecRunner.html | 1 - test/spec/SpecRunnerUtils.js | 23 ++----------- 5 files changed, 88 insertions(+), 43 deletions(-) create mode 100644 src/utils/Params.js diff --git a/src/brackets.js b/src/brackets.js index d2809179696..12d8b9cfc02 100644 --- a/src/brackets.js +++ b/src/brackets.js @@ -78,18 +78,16 @@ define(function (require, exports, module) { Dialogs = require("widgets/Dialogs"), ExtensionLoader = require("utils/ExtensionLoader"), SidebarView = require("project/SidebarView"), - Async = require("utils/Async"); + Async = require("utils/Async"), + Params = require("utils/Params").Params; // Local variables var bracketsReady = false, bracketsReadyHandlers = [], - paramMap = [], - params = window.document.location.search.substring(1).split('&'); + params = new Params(); - params.forEach(function (param) { - var p = param.split('='); - paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); - }); + // read URL params + params.parseLocation(); //Load modules that self-register and just need to get included in the main project require("document/ChangedDocumentTracker"); @@ -182,7 +180,8 @@ define(function (require, exports, module) { // TODO: (issue 1029) Add timeout to main extension loading promise, so that we always call this function // Making this fix will fix a warning (search for issue 1029) related to the brackets 'ready' event. function _initExtensions() { - var paths = paramMap.extensions || "default,user"; + // allow unit tests to override which plugin folder(s) to load + var paths = params.get("extensions") || "default,user"; return Async.doInParallel(paths.split(","), function (item) { return ExtensionLoader.loadAllExtensionsInNativeDirectory( diff --git a/src/utils/Params.js b/src/utils/Params.js new file mode 100644 index 00000000000..ba4b0b4111e --- /dev/null +++ b/src/utils/Params.js @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + + +/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */ +/*global define, window */ + +define(function (require, exports, module) { + "use strict"; + + function Params() { + this._store = {}; + } + + Params.prototype.parseLocation = function () { + var urlParams = window.document.location.search.substring(1).split("&"), + p, + self = this; + + urlParams.forEach(function (param) { + p = param.split("="); + self._store[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + }); + }; + + Params.prototype.put = function (name, value) { + this._store[name] = value; + }; + + Params.prototype.get = function (name) { + return this._store[name]; + }; + + Params.prototype.toString = function () { + var strs = [], + self = this; + + Object.keys(self._store).forEach(function (key) { + strs.push(encodeURIComponent(key) + "=" + encodeURIComponent(self._store[key])); + }); + + return strs.join("&"); + }; + + // Define public API + exports.Params = Params; +}); \ No newline at end of file diff --git a/test/BootstrapReporter.js b/test/BootstrapReporter.js index 72b1e9791a3..59b516c3687 100644 --- a/test/BootstrapReporter.js +++ b/test/BootstrapReporter.js @@ -1,32 +1,29 @@ /*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50, forin: true */ -/*global jasmine, document */ -(function ($) { +/*global jasmine, $, define, document, require */ +define(function (require, exports, module) { 'use strict'; + + var Params = require("utils/Params").Params; jasmine.BootstrapReporter = function (doc, filter) { - this._paramMap = {}; this.document = doc || document; this._env = jasmine.getEnv(); + this.params = new Params(); + this.params.parseLocation(); // parse querystring var self = this, - params = this.document.location.search.substring(1).split('&'), i, p; - for (i = 0; i < params.length; i++) { - p = params[i].split('='); - this._paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); - } - - this._runAll = this._paramMap.spec === "All"; + this._runAll = this.params.get("spec") === "All"; // _topLevelFilter is applied first - selects Performance vs. Unit test suites this._topLevelFilter = filter; // Jasmine's runner uses the specFilter to choose which tests to run. // If you selected an option other than "All" this will be a subset of all tests loaded. - this._env.specFilter = this.createSpecFilter(this._paramMap.spec); + this._env.specFilter = this.createSpecFilter(this.params.get("spec")); this._runner = this._env.currentRunner(); // build DOM immediately @@ -187,7 +184,7 @@ this._createSuiteList(); // highlight the current suite - topLevelData = (this._paramMap.spec) ? this._topLevelSuiteMap[this._paramMap.spec] : null; + topLevelData = (this.params.get("spec")) ? this._topLevelSuiteMap[this.params.get("spec")] : null; if (topLevelData) { topLevelData.$listItem.toggleClass("active", true); @@ -229,7 +226,7 @@ passed, data = this._topLevelSuiteMap[suite.getFullName()]; - if ((suite.getFullName() === this._paramMap.spec) && data) { + if ((suite.getFullName() === this.params.get("spec")) && data) { passed = results.passed(); data.$badgeAll.hide(); @@ -354,4 +351,4 @@ jasmine.BootstrapReporter.prototype.log = function (str) { }; -}(window.jQuery)); +}); diff --git a/test/SpecRunner.html b/test/SpecRunner.html index d632d8f9762..78c5e4a2ae5 100644 --- a/test/SpecRunner.html +++ b/test/SpecRunner.html @@ -37,7 +37,6 @@ - diff --git a/test/spec/SpecRunnerUtils.js b/test/spec/SpecRunnerUtils.js index d6b09c46f7e..178bb0d77c1 100644 --- a/test/spec/SpecRunnerUtils.js +++ b/test/spec/SpecRunnerUtils.js @@ -31,7 +31,8 @@ define(function (require, exports, module) { Commands = require("command/Commands"), FileUtils = require("file/FileUtils"), Async = require("utils/Async"), - DocumentManager = require("document/DocumentManager"); + DocumentManager = require("document/DocumentManager"), + Params = require("utils/Params").Params; var TEST_PREFERENCES_KEY = "com.adobe.brackets.test.preferences", OPEN_TAG = "{{", @@ -60,24 +61,6 @@ define(function (require, exports, module) { return path.join("/"); } - function Params() { - this.params = []; - } - - Params.prototype.push = function (name, value) { - this.params.push({name: name, value: value}); - }; - - Params.prototype.toString = function () { - var strs = []; - - this.params.forEach(function (param) { - strs.push(encodeURIComponent(param.name) + "=" + encodeURIComponent(param.value)); - }); - - return strs.join("&"); - }; - /** * Utility for tests that wait on a Promise to complete. Placed in the global namespace so it can be used * similarly to the standards Jasmine waitsFor(). Unlike waitsFor(), must be called from INSIDE @@ -150,7 +133,7 @@ define(function (require, exports, module) { var params = new Params(); // setup extension loading in the test window - params.push("extensions", _doLoadExtensions ? "default,user" : "default"); + params.put("extensions", _doLoadExtensions ? "default,user" : "default"); _testWindow = window.open(getBracketsSourceRoot() + "/index.html?" + params.toString(), "_blank", optionsStr); From 632ae37cb6db4696576e13e16a7769861d63f1ac Mon Sep 17 00:00:00 2001 From: Jason San Jose Date: Thu, 19 Jul 2012 18:00:46 -0700 Subject: [PATCH 3/5] Update SpecRunner to use Params --- test/SpecRunner.js | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/test/SpecRunner.js b/test/SpecRunner.js index 27b91b1b8e4..ec7334a6f35 100644 --- a/test/SpecRunner.js +++ b/test/SpecRunner.js @@ -44,7 +44,11 @@ define(function (require, exports, module) { ExtensionLoader = require("utils/ExtensionLoader"), Async = require("utils/Async"), FileUtils = require("file/FileUtils"), - Menus = require("command/Menus"); + Menus = require("command/Menus"), + Params = require("utils/Params").Params; + + // Jasmine reporter UI + require("test/BootstrapReporter"); // TODO: Issue 949 - the following code should be shared // Load modules that self-register and just need to get included in the main project @@ -54,21 +58,10 @@ define(function (require, exports, module) { require("test/UnitTestSuite"); require("test/PerformanceTestSuite"); - var suite; - - function getParamMap() { - var params = document.location.search.substring(1).split('&'), - paramMap = {}, - i, - p; + var suite, + params = new Params(); - for (i = 0; i < params.length; i++) { - p = params[i].split('='); - paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); - } - - return paramMap; - } + params.parseLocation(); function _loadExtensionTests(suite) { // augment jasmine to identify extension unit tests @@ -137,7 +130,7 @@ define(function (require, exports, module) { // modules. The extension will only be able to load modules that have already been loaded once. brackets.getModule = require; - suite = getParamMap().suite || localStorage.getItem("SpecRunner.suite") || "UnitTestSuite"; + suite = params.get("suite") || localStorage.getItem("SpecRunner.suite") || "UnitTestSuite"; // Create a top-level filter to show/hide performance and extensions tests var isPerfSuite = (suite === "PerformanceTestSuite"), From 2edf72f6c1e6afd4e4f18bacb6f8fa791fd6d9d2 Mon Sep 17 00:00:00 2001 From: Jason San Jose Date: Fri, 20 Jul 2012 09:41:52 -0700 Subject: [PATCH 4/5] Rename Params to UrlParams, parseLocation to parse. --- src/brackets.js | 6 +++--- src/utils/{Params.js => UrlParams.js} | 20 +++++++++++++------- test/BootstrapReporter.js | 6 +++--- test/SpecRunner.js | 6 +++--- test/spec/SpecRunnerUtils.js | 4 ++-- 5 files changed, 24 insertions(+), 18 deletions(-) rename src/utils/{Params.js => UrlParams.js} (80%) diff --git a/src/brackets.js b/src/brackets.js index 12d8b9cfc02..547c26dde66 100644 --- a/src/brackets.js +++ b/src/brackets.js @@ -79,15 +79,15 @@ define(function (require, exports, module) { ExtensionLoader = require("utils/ExtensionLoader"), SidebarView = require("project/SidebarView"), Async = require("utils/Async"), - Params = require("utils/Params").Params; + UrlParams = require("utils/UrlParams").UrlParams; // Local variables var bracketsReady = false, bracketsReadyHandlers = [], - params = new Params(); + params = new UrlParams(); // read URL params - params.parseLocation(); + params.parse(); //Load modules that self-register and just need to get included in the main project require("document/ChangedDocumentTracker"); diff --git a/src/utils/Params.js b/src/utils/UrlParams.js similarity index 80% rename from src/utils/Params.js rename to src/utils/UrlParams.js index ba4b0b4111e..83bdeb84085 100644 --- a/src/utils/Params.js +++ b/src/utils/UrlParams.js @@ -28,12 +28,18 @@ define(function (require, exports, module) { "use strict"; - function Params() { + function UrlParams() { this._store = {}; } - Params.prototype.parseLocation = function () { - var urlParams = window.document.location.search.substring(1).split("&"), + UrlParams.prototype.parse = function (url) { + if (url) { + url = url.substring(indexOf("?") + 1); + } else { + url = window.document.location.search.substring(1); + } + + var urlParams = url.split("&"), p, self = this; @@ -43,15 +49,15 @@ define(function (require, exports, module) { }); }; - Params.prototype.put = function (name, value) { + UrlParams.prototype.put = function (name, value) { this._store[name] = value; }; - Params.prototype.get = function (name) { + UrlParams.prototype.get = function (name) { return this._store[name]; }; - Params.prototype.toString = function () { + UrlParams.prototype.toString = function () { var strs = [], self = this; @@ -63,5 +69,5 @@ define(function (require, exports, module) { }; // Define public API - exports.Params = Params; + exports.UrlParams = UrlParams; }); \ No newline at end of file diff --git a/test/BootstrapReporter.js b/test/BootstrapReporter.js index 59b516c3687..fd1eafb0e05 100644 --- a/test/BootstrapReporter.js +++ b/test/BootstrapReporter.js @@ -3,13 +3,13 @@ define(function (require, exports, module) { 'use strict'; - var Params = require("utils/Params").Params; + var UrlParams = require("utils/UrlParams").UrlParams; jasmine.BootstrapReporter = function (doc, filter) { this.document = doc || document; this._env = jasmine.getEnv(); - this.params = new Params(); - this.params.parseLocation(); + this.params = new UrlParams(); + this.params.parse(); // parse querystring var self = this, diff --git a/test/SpecRunner.js b/test/SpecRunner.js index ec7334a6f35..f820271ceab 100644 --- a/test/SpecRunner.js +++ b/test/SpecRunner.js @@ -45,7 +45,7 @@ define(function (require, exports, module) { Async = require("utils/Async"), FileUtils = require("file/FileUtils"), Menus = require("command/Menus"), - Params = require("utils/Params").Params; + UrlParams = require("utils/UrlParams").UrlParams; // Jasmine reporter UI require("test/BootstrapReporter"); @@ -59,9 +59,9 @@ define(function (require, exports, module) { require("test/PerformanceTestSuite"); var suite, - params = new Params(); + params = new UrlParams(); - params.parseLocation(); + params.parse(); function _loadExtensionTests(suite) { // augment jasmine to identify extension unit tests diff --git a/test/spec/SpecRunnerUtils.js b/test/spec/SpecRunnerUtils.js index 178bb0d77c1..17bce83b695 100644 --- a/test/spec/SpecRunnerUtils.js +++ b/test/spec/SpecRunnerUtils.js @@ -32,7 +32,7 @@ define(function (require, exports, module) { FileUtils = require("file/FileUtils"), Async = require("utils/Async"), DocumentManager = require("document/DocumentManager"), - Params = require("utils/Params").Params; + UrlParams = require("utils/UrlParams").UrlParams; var TEST_PREFERENCES_KEY = "com.adobe.brackets.test.preferences", OPEN_TAG = "{{", @@ -130,7 +130,7 @@ define(function (require, exports, module) { optionsStr = "left=" + testWindowX + ",top=" + testWindowY + ",width=" + testWindowWid + ",height=" + testWindowHt; - var params = new Params(); + var params = new UrlParams(); // setup extension loading in the test window params.put("extensions", _doLoadExtensions ? "default,user" : "default"); From 8c501a8add847573ed890c9de9aa3869ac40a035 Mon Sep 17 00:00:00 2001 From: Jason San Jose Date: Fri, 20 Jul 2012 09:45:39 -0700 Subject: [PATCH 5/5] Add docs --- src/utils/UrlParams.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/utils/UrlParams.js b/src/utils/UrlParams.js index 83bdeb84085..5fd145a49af 100644 --- a/src/utils/UrlParams.js +++ b/src/utils/UrlParams.js @@ -28,10 +28,17 @@ define(function (require, exports, module) { "use strict"; + /** + * Convert between URL querystring and name/value pairs. Decodes and encodes URL parameters. + */ function UrlParams() { this._store = {}; } + /** + * Parse the window location by default. Optionally specify a URL to parse. + * @param {string} url + */ UrlParams.prototype.parse = function (url) { if (url) { url = url.substring(indexOf("?") + 1); @@ -49,14 +56,26 @@ define(function (require, exports, module) { }); }; + /** + * Store a name/value string pair + * @param {!string} name + * @param {!string} value + */ UrlParams.prototype.put = function (name, value) { this._store[name] = value; }; + /** + * Retreive a value by name + * @param {!string} name + */ UrlParams.prototype.get = function (name) { return this._store[name]; }; + /** + * Encode name/value pairs as URI components. + */ UrlParams.prototype.toString = function () { var strs = [], self = this;