1
0
mirror of https://github.com/adobe/brackets.git synced 2024-11-20 09:53:00 +01:00

Add a test for QuickOpen and a custom matcher for editor cursor position.

The QuickOpen test checks three things currently:

1. Ability to open a file with QuickOpen with the expected matching
2. Ability to jump to a line
3. The selected line is centered
This commit is contained in:
Kevin Dangoor 2013-01-18 10:47:13 -05:00
parent 6c9ba17000
commit 77a1c59d67
7 changed files with 523 additions and 1 deletions

View File

@ -23,6 +23,7 @@
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, $, window, setTimeout */
/*unittests: QuickOpen*/
/*
* Displays an auto suggest pop-up list of files to allow the user to quickly navigate to a file and lines

View File

@ -54,6 +54,8 @@ define(function (require, exports, module) {
// Load modules that self-register and just need to get included in the main project
require("document/ChangedDocumentTracker");
require("thirdparty/smart-auto-complete/jquery.smart_autocomplete");
// TODO (#2155): These are used by extensions via brackets.getModule(), so tests that run those
// extensions need these to be required up front. We need a better solution for this eventually.

View File

@ -48,6 +48,7 @@ define(function (require, exports, module) {
require("spec/NativeMenu-test");
require("spec/PreferencesManager-test");
require("spec/ProjectManager-test");
require("spec/QuickOpen-test");
require("spec/UpdateNotification-test");
require("spec/ViewUtils-test");
require("spec/WorkingSetView-test");

View File

@ -0,0 +1,293 @@
<!DOCTYPE html>
<html>
<body>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
<div>sometext</div>
</body>
</html>

View File

@ -0,0 +1,7 @@
<!DOCTYPE html>
<html>
<body>
<h1>No Cat Pictures</h1>
<p>This is your cat picture-free haven on the Internet. Congratulations for finding this site.</p>
</body>
</html>

185
test/spec/QuickOpen-test.js Normal file
View File

@ -0,0 +1,185 @@
/*
* Copyright (c) 2013 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, describe, it, expect, beforeEach, afterEach, waitsFor, runs, window, $, jasmine, setTimeout */
/*unittests: QuickOpen*/
define(function (require, exports, module) {
'use strict';
var Commands = require("command/Commands"),
KeyEvent = require("utils/KeyEvent"),
SpecRunnerUtils = require("spec/SpecRunnerUtils");
describe("QuickOpen", function () {
var testPath = SpecRunnerUtils.getTestPath("/spec/QuickOpen-test-files");
var brackets, test$, executeCommand, EditorManager, DocumentManager;
beforeEach(function () {
runs(function () {
SpecRunnerUtils.createTestWindowAndRun(this, function (testWindow) {
brackets = testWindow.brackets;
test$ = testWindow.$;
executeCommand = testWindow.executeCommand;
EditorManager = brackets.test.EditorManager;
DocumentManager = brackets.test.DocumentManager;
});
});
});
afterEach(function () {
SpecRunnerUtils.closeTestWindow();
});
function getSearchBar() {
return test$(".modal-bar");
}
function getSearchField() {
return test$(".modal-bar input[type='text']");
}
function expectSearchBarOpen() {
expect(getSearchBar()[0]).toBeDefined();
}
function expectSearchBarClosed() {
expect(getSearchBar()[0]).not.toBeDefined();
}
function enterSearchText(str, timeoutLength) {
timeoutLength = timeoutLength || 10;
expectSearchBarOpen();
var input = getSearchField()[0];
// We need to simulate typing into the field in order to get the QuickOpen matching code to
// run.
var i;
for (i = 0; i < str.length; i++) {
SpecRunnerUtils.simulateKeyEvent(KeyEvent["DOM_VK_" + str[i]], "keydown", input);
}
// We still set the input value as well because that is read by other code.
// setTimeout is used to turn the event loop so that the search text is not placed in
// the text field until after the keydown code has received the events.
//
// timeoutLength is configurable because some uses may take longer than others
setTimeout(function () {
getSearchField().val(str);
}, timeoutLength);
}
function pressEnter() {
expectSearchBarOpen();
// Using keyup here because of inside knowledge of how the events are processed
// on the QuickOpen input.
SpecRunnerUtils.simulateKeyEvent(KeyEvent.DOM_VK_RETURN, "keyup", getSearchField()[0]);
}
it("can open a file and jump to a line, centering that line on the screen", function () {
var hostOpened = false;
var err = false;
var workingSet = [];
SpecRunnerUtils.loadProjectInTestWindow(testPath);
runs(function () {
SpecRunnerUtils.openProjectFiles(workingSet).done(function (documents) {
hostOpened = true;
}).fail(function () {
err = true;
});
});
waitsFor(function () { return hostOpened && !err; }, "window opening timeout", 1000);
runs(function () {
executeCommand(Commands.NAVIGATE_QUICK_OPEN);
// need to set the timeout length here to ensure that it has a chance to load the file
// list.
enterSearchText("lines", 100);
});
waitsFor(function () {
return getSearchField().val() === "lines";
}, "filename entry timeout", 1000);
runs(function () {
pressEnter();
});
waitsFor(function () {
return EditorManager.getCurrentFullEditor() !== null;
}, "file opening timeout", 3000);
runs(function () {
// Make sure we've opened the right file. It should open the longer one, because
// of the scoring in the StringMatch algorithm.
expect(DocumentManager.getCurrentDocument().file.name).toEqual("lotsOfLines.html");
executeCommand(Commands.NAVIGATE_GOTO_LINE);
enterSearchText(":50");
});
waitsFor(function () {
return getSearchField().val() === ":50";
}, "goto line entry timeout", 1000);
var eventLooped = false;
runs(function () {
pressEnter();
setTimeout(function () {
eventLooped = true;
}, 10);
});
waitsFor(function () { return eventLooped; });
runs(function () {
var editor = EditorManager.getCurrentFullEditor();
var scrollPos = editor.getScrollPos();
// The user enters a 1-based number, but the reported position
// is 0 based, so we check for 49.
expect(editor).toHaveCursorPosition(49, 0);
// We expect the result to be scrolled roughly to the middle of the window.
expect(scrollPos.y).toBeGreaterThan(400);
expect(scrollPos.y).toBeLessThan(500);
eventLooped = false;
setTimeout(function () {
eventLooped = true;
}, 10);
});
waitsFor(function () { return eventLooped; });
});
});
});

View File

@ -791,7 +791,40 @@ define(function (require, exports, module) {
return deferred.promise();
}
beforeEach(function () {
this.addMatchers({
toHaveCursorPosition: function (line, ch) {
var editor = this.actual;
var selection = editor.getSelection();
var notString = this.isNot ? "not " : "";
var start = selection.start;
var end = selection.end;
var selectionMoreThanOneCharacter = start.line !== end.line || start.ch !== end.ch;
this.message = function () {
var message = "Expected the cursor to " + notString + "be at (" + line + ", " + ch +
") but it was actually at (" + start.line + ", " + start.ch + ")";
if (!this.isNot && selectionMoreThanOneCharacter) {
message += " and more than one character was selected.";
}
return message;
};
var positionsMatch = start.line === line && start.ch === ch;
// when adding the not operator, it's confusing to check both the size of the
// selection and the position. We just check the position in that case.
if (this.isNot) {
return positionsMatch;
} else {
return !selectionMoreThanOneCharacter && positionsMatch;
}
}
});
});
exports.TEST_PREFERENCES_KEY = TEST_PREFERENCES_KEY;
exports.chmod = chmod;