More Editor Option Handlers Tests #3231

Merged
merged 8 commits into from Apr 7, 2013

Projects

None yet

3 participants

@TomMalbran
Collaborator

I added tests for show line numbers and auto close brackets and refactored the code to reduce the code repetition. The difference is all wrong, since I added new indentation and new helper functions, but the functionality is all the same as before for the older tests.

@TomMalbran TomMalbran commented on the diff Mar 23, 2013
test/spec/SpecRunnerUtils.js
if (oEvent.initKeyboardEvent) {
- oEvent.initKeyboardEvent(event, true, true, doc.defaultView, false, false, false, false, key, key);
+ oEvent.initKeyboardEvent(event, true, true, doc.defaultView, key, 0, false, false, false, false);
} else {
@TomMalbran
TomMalbran Mar 23, 2013 collaborator

The parameters where passed in the wrong order here: http://stackoverflow.com/questions/12955779/how-can-i-add-a-keycode-to-a-synthetic-keyboardevent-in-webkit.

The charCode part was needed to be used in Strings.fromCharCode in CodeMirror.

@TomMalbran TomMalbran commented on the diff Mar 23, 2013
test/spec/ViewUtils-test.js
@@ -1,5 +1,24 @@
/*
- * Copyright 2012 Adobe Systems Incorporated. All Rights Reserved.
@TomMalbran
TomMalbran Mar 23, 2013 collaborator

I noticed that this file didn't had the correct Copyright, so I added it. But I can remove it if this wasn't a mistake.

@jbalsas
jbalsas Apr 5, 2013 Adobe Systems Incorporated member

It never hurts, but make it 2013 instead ;)

@jbalsas jbalsas was assigned Apr 4, 2013
@jbalsas
Member
jbalsas commented Apr 4, 2013

Reviewing

@jbalsas jbalsas and 1 other commented on an outdated diff Apr 4, 2013
test/spec/EditorOptionHandlers-test.js
@@ -62,11 +71,20 @@ define(function (require, exports, module) {
SpecRunnerUtils.closeTestWindow();
});
- function checkLineWrapping(firstPos, secondPos, shouldWrap, inlineEditor) {
+ function getEditor(isInlineEditor) {
@jbalsas
jbalsas Apr 4, 2013 Adobe Systems Incorporated member

I'm not really fond of this method, and the consequences to the rest of methods' parameter lists... As we're only testing one editor at a time, I'd prefer if we could tweak openEditor and openInlineEditor so that at the end, and before the checks, it would be pointing to the right editor (full or inline).

However, unless you can do that quickly, it's not probably worth the effort, so don't worry too much about it.

@jbalsas
jbalsas Apr 4, 2013 Adobe Systems Incorporated member

If we do keep it this way, I'd probably call the parameter just inline as the method getEditor already gives away the rest ;)

@TomMalbran
TomMalbran Apr 4, 2013 collaborator

I like that idea, and I have it implemented and working. Will push it with the rest of the review fixes, once the review is done :)

@jbalsas jbalsas commented on an outdated diff Apr 4, 2013
test/spec/EditorOptionHandlers-test.js
@@ -62,11 +71,20 @@ define(function (require, exports, module) {
SpecRunnerUtils.closeTestWindow();
});
- function checkLineWrapping(firstPos, secondPos, shouldWrap, inlineEditor) {
+ function getEditor(isInlineEditor) {
+ if (isInlineEditor) {
+ return EditorManager.getCurrentFullEditor().getInlineWidgets()[0].editors[0];
+ } else {
+ return EditorManager.getCurrentFullEditor();
+ }
+ }
+
+
+ function checkLineWrapping(firstPos, secondPos, shouldWrap, isInlineEditor) {
@jbalsas
jbalsas Apr 4, 2013 Adobe Systems Incorporated member

Very minor nit: It would make more sense for this parameter to be called atInlineEditor instead, but then it looks weird in the getEditor call, so I'd just leave it as inlineEditor as before. Same for all other isInlineEditor parameters

@jbalsas jbalsas and 1 other commented on an outdated diff Apr 4, 2013
test/spec/EditorOptionHandlers-test.js
+ } else {
+ editor.setCursorPos(startSel);
+ }
+
+ SpecRunnerUtils.simulateKeyEvent(keyCode, keyCode === BACKSPACE ? "keydown" : "keypress", input);
+
+ line = editor._codeMirror.getLine(0).substr(0, expectedText.length);
+ expect(line).toBe(expectedText);
+ });
+ }
+
+
+ // Helper functions to open editors / toggle options
+ function openEditor(fullPath) {
+ runs(function () {
+ var promise = CommandManager.execute(Commands.FILE_ADD_TO_WORKING_SET, {fullPath: fullPath});
waitsForDone(promise, "Open into working set");
});
@jbalsas
jbalsas Apr 4, 2013 Adobe Systems Incorporated member

We could add here

runs(function () {
    editor = EditorManager.getCurrentFullEditor();
});

with editor being declared for the suite and cleaned up before each test. Then, we won't need to get the editor in the helper methods, and the isInlineEditor won't be needed.

This seems somewhat clearer to me, but I could be convinced otherwise :)

@TomMalbran
TomMalbran Apr 4, 2013 collaborator

Yes. This is exactly what I did a few minutes ago.

@jbalsas
jbalsas Apr 4, 2013 Adobe Systems Incorporated member

You're too damn fast ;)

@jbalsas jbalsas commented on the diff Apr 4, 2013
test/spec/EditorOptionHandlers-test.js
waitsForDone(promise, "Open into working set");
});
+ }
+ function openAnotherEditor(fullpath) {
+ runs(function () {
+ // Open another document and bring it to the front
+ waitsForDone(FileViewController.openAndSelectDocument(fullpath, FileViewController.PROJECT_MANAGER),
+ "FILE_OPEN on file timeout", 1000);
+ });
@jbalsas
jbalsas Apr 4, 2013 Adobe Systems Incorporated member

Same here as in openEditor

@jbalsas jbalsas commented on an outdated diff Apr 4, 2013
test/spec/EditorOptionHandlers-test.js
runs(function () {
// Open inline editor onto test.css's ".testClass" rule
- promise = SpecRunnerUtils.toggleQuickEditAtOffset(EditorManager.getCurrentFullEditor(), {line: 8, ch: 11});
+ var promise = SpecRunnerUtils.toggleQuickEditAtOffset(EditorManager.getCurrentFullEditor(), {line: 8, ch: 11});
waitsForDone(promise, "Open inline editor");
});
@jbalsas
jbalsas Apr 4, 2013 Adobe Systems Incorporated member

Same here as in openEditor, but getting the inline one ;)

@jbalsas jbalsas commented on the diff Apr 4, 2013
test/spec/EditorOptionHandlers-test.js
});
});
-
- it("should NOT show active line in inline editor by default", function () {
- var promise,
- inlineEditor,
- lineInfo;
-
- runs(function () {
- promise = CommandManager.execute(Commands.FILE_ADD_TO_WORKING_SET, {fullPath: HTML_FILE});
- waitsForDone(promise, "Open into working set");
+
+
+ describe("Toggle Line Numbers", function () {
@jbalsas
jbalsas Apr 4, 2013 Adobe Systems Incorporated member

We should add at least one test for not showing numbers on inline editors

@jbalsas jbalsas and 1 other commented on an outdated diff Apr 5, 2013
test/spec/EditorOptionHandlers-test.js
runs(function () {
- promise = CommandManager.execute(Commands.FILE_ADD_TO_WORKING_SET, {fullPath: HTML_FILE});
+ var editor = getEditor(isInlineEditor),
+ gutterElement;
+
+ expect(editor).toBeTruthy();
+ gutterElement = editor._codeMirror.getGutterElement();
+
+ if (shouldShow) {
+ expect(gutterElement.style.display).toBe("");
+ } else {
+ expect(gutterElement.style.display).toBe("none");
+ }
@jbalsas
jbalsas Apr 5, 2013 Adobe Systems Incorporated member

I'm not sure if this is a proper way to test this. Couldn't we have at some point more gutter elements other than line numbers? In that case, I'd expect the gutter element to remain visible even if line numbers are not.

We could check for an element .CodeMirror-gutter .CodeMirror-linenumbers or something like that

@TomMalbran
TomMalbran Apr 5, 2013 collaborator

You are right, I checked that there can be multiple gutters (didn't knew it before), but found another easy way to check if there is a linenumbers gutter displayed.

@jbalsas jbalsas and 1 other commented on an outdated diff Apr 5, 2013
test/spec/EditorOptionHandlers-test.js
});
});
- it("should style active line after turning it on", function () {
- var promise,
- editor,
- lineInfo;
+
+ describe("Toggle Auto Close Brackets", function () {
@jbalsas
jbalsas Apr 5, 2013 Adobe Systems Incorporated member

The feature is actually closed Auto Close Braces, and also works for other chars such as "", '', (), {}. We should change the suite name.

It's probably not critical at all, as I'd assume if it works for one, it should for the others, but if it's not too much complicated to add those additional checks (pass an array of chars to checkCloseBrackets, for example?, or just do several checks in the tests...)

@jbalsas
jbalsas Apr 5, 2013 Adobe Systems Incorporated member

I was checking the codemirror addon and I don't think it's worth the extra noise to add those other checks for now

@TomMalbran
TomMalbran Apr 5, 2013 collaborator

I changed all the names already.

I figure if it worked for 1, it should work for all, since every key is added to the key map and assigned the same function making all of them work in the same way. Anyway, maybe 1 extra test just to check that it works for all the braces, might be useful?

@jbalsas
jbalsas Apr 5, 2013 Adobe Systems Incorporated member

No need, imho. Would probably be just meaningless tests.

@jbalsas
jbalsas Apr 5, 2013 Adobe Systems Incorporated member

We're missing one though, for auto-close in inline editors

@jbalsas jbalsas commented on an outdated diff Apr 5, 2013
test/spec/EditorOptionHandlers-test.js
+ var editor = getEditor(isInlineEditor),
+ input,
+ line;
+
+ expect(editor).toBeTruthy();
+ input = editor._codeMirror.getInputField();
+
+ if (endSel) {
+ editor.setSelection(startSel, endSel);
+ } else {
+ editor.setCursorPos(startSel);
+ }
+
+ SpecRunnerUtils.simulateKeyEvent(keyCode, keyCode === BACKSPACE ? "keydown" : "keypress", input);
+
+ line = editor._codeMirror.getLine(0).substr(0, expectedText.length);
@jbalsas
jbalsas Apr 5, 2013 Adobe Systems Incorporated member

I'm not very comfortable with this substr ... not sure if it's possible, but at some point we may be adding some characters outside that range and not be aware of it. If the problem is that the css file we're using to test is too long, I'd suggest creating a different one for this, and adjust it so we can compare the full line.

Also, it should be getLine(startSel.line).

@jbalsas jbalsas commented on an outdated diff Apr 5, 2013
test/spec/EditorOptionHandlers-test.js
});
});
- it("should style active line after turning it on", function () {
- var promise,
- editor,
- lineInfo;
+
+ describe("Toggle Auto Close Brackets", function () {
+ it("should NOT auto close brackets in main editor by default", function () {
+ openEditor(JS_FILE);
+ checkCloseBrackets({line: 0, ch: 35}, null, OPEN_BRACKET, "var myContent = \"This is awesome!\";", false);
@jbalsas
jbalsas Apr 5, 2013 Adobe Systems Incorporated member

I'll need some explaining here, as I'd expect to have var myContent = "This is awesome!";[ after typing [ with auto-close-braces off. Is this because of how codemirror or the addon handles the keypresses?

@jbalsas
Member
jbalsas commented Apr 5, 2013

@TomMalbran Done with review. Looks good overall, and nice refactors out there ;)

I'll have some sleep time, so don't go rushing to fix everything!

@TomMalbran
Collaborator

@jbalsas Thanks again for the review! I think I covered all your comments.

I'll need some explaining here, as I'd expect to have var myContent = "This is awesome!";[ after typing [ with auto-close-braces off. Is this because of how codemirror or the addon handles the keypresses?

I am not sure why it doesn't add the key. I do know that the function that handles the keypresses in CodeMirror searches through the keymaps and applies the function that it finds, so that makes the auto close braces work, but I do not know why it does nothing when it doesn't find a function. I still haven't find how CodeMirror handles the inputs, and I did tried several simulation and this is the one that works better.

@jbalsas jbalsas commented on an outdated diff Apr 5, 2013
test/spec/EditorOptionHandlers-test.js
runs(function () {
- promise = CommandManager.execute(Commands.FILE_ADD_TO_WORKING_SET, {fullPath: HTML_FILE});
- waitsForDone(promise, "Open into working set");
+ var gutterElement, $gutter;
+
+ expect(editor).toBeTruthy();
+ gutterElement = editor._codeMirror.getGutterElement();
+ $gutter = testWindow.$(gutterElement).find(".CodeMirror-linenumbers");
@jbalsas
jbalsas Apr 5, 2013 Adobe Systems Incorporated member

Why not just $(gutterElement).find(".CodeMirror-linenumbers") ?

Also, $gutter seems somehow misleading. How about $lineNumbers?

@jbalsas jbalsas commented on an outdated diff Apr 5, 2013
test/spec/EditorOptionHandlers-test.js
@@ -56,17 +67,17 @@ define(function (require, exports, module) {
SpecRunnerUtils.loadProjectInTestWindow(testPath);
});
+ editor = null;
@jbalsas
jbalsas Apr 5, 2013 Adobe Systems Incorporated member

I'd rather have editor initialized to null, and then nulled again afterEach test.

@jbalsas
Member
jbalsas commented Apr 5, 2013

@TomMalbran Re-review done, just two minor comments and we can merge this.

I'm still not happy that strange missing bracket character issue... I'll try to spend some time on if afterwards.

@jbalsas jbalsas and 2 others commented on an outdated diff Apr 5, 2013
test/spec/EditorOptionHandlers-test.js
});
afterEach(function () {
SpecRunnerUtils.closeTestWindow();
});
- function checkLineWrapping(firstPos, secondPos, shouldWrap, inlineEditor) {
+
+ function checkLineWrapping(firstPos, secondPos, shouldWrap) {
@jbalsas
jbalsas Apr 5, 2013 Adobe Systems Incorporated member

One last comment, if you're up to it.

I think all these helper check methods should receive as a first parameter the editor to check against. This way, the helper methods are agnostic of what happens on the outside, and will be the test the responsible for deciding which editor to check. I think this is a bit more robust than just relying on the editor being set.

@TomMalbran
TomMalbran Apr 6, 2013 collaborator

That is kind of how it was working before with the isInlineEditor parameter and using the getEditor function. But to implement it with the new code, the open functions could return the editor instead of using the global variable, and then then send that to the check function. Would that work better? It might look better.

@jbalsas
jbalsas Apr 6, 2013 Adobe Systems Incorporated member

Yes, ideally the openEditor functions would return a promise that would resolve with the opened editor. However, that will add lots of code and make the tests less readable. You can try, though, to see if there's an easy way, but I think we can compromise for now in at least passing the editor to the helper methods so that those remain independent.

@TomMalbran
TomMalbran Apr 6, 2013 collaborator

I tried passing the editor as the first parameter but it still doesn't work, I believe that the problem is that the passed editor hasn't been resolved yet, so when the run function from the check functions work, they will use the undefined editor. Anyway, since the test already calls any of the open editor functions (depending on the test made) and since the editor variable gets nulled after each test, it already decides which editor to use without having to explicitly passed as a parameter, and since everything is run inside the run function it should work synchronously.

@jbalsas
jbalsas Apr 6, 2013 Adobe Systems Incorporated member

Yeah, this can be a bit tricky with all the runs and waitsFor...... another option would be to use your previous getEditor method inside the tests to resolve the editor variable, and then pass it to the helper methods.

What do you think? Could you give that a try? Otherwise, we can leave this as is.

@RaymondLim
RaymondLim Apr 6, 2013 collaborator

I tried passing the editor as the first parameter but it still doesn't work, I believe that the problem is that the passed editor hasn't been >resolved yet, so when the run function from the check functions work, they will use the undefined editor.

You need to wrap your call to the helper function with runs(function () { helperFunction(); }); since getEditor is an async operation.

@RaymondLim
RaymondLim Apr 6, 2013 collaborator

Ignore my previous comment. I saw that you have the entire helper function wrapped in runs.

@TomMalbran
TomMalbran Apr 6, 2013 collaborator

Yeah, this can be a bit tricky with all the runs and waitsFor...... another option would be to use your previous getEditor method inside the tests to resolve the editor variable, and then pass it to the helper methods.

That would be the same as now, except if the get is inside the run functions of the check method as before.

Edit: I managed to make it work making the getEditor and the check function run inside a run function inside the tests, but that kind of makes it look worst. I tried then just using a deferred response to return the result from the open functions and that doesn't look as nice as before, but is better than the run function.

@jbalsas
jbalsas Apr 6, 2013 Adobe Systems Incorporated member

You should put the runs around the helper method call (inside the it clause). That way, all promises would have resolved, and you can get the proper editor and pass it to the check methods. Also, the runs in the check methods should now not be needed anymore, as we'd be waiting for the promises to resolve outside them.

I'd suggest something like:

function checkLineWrapping(editor, ...) {
   //expectSomethingFromEditor
}

it("should do something", function () {
  openEditor(HTML_FILE);
  runs(function() {
    var editor = getFullEditor(),
        inlineEditor = getInlineEditor(0);

    checkLineWrapping(editor, ...);
    checkLineWrapping(inlineEditor, ...);
  }
});

This gives us also the possibility of easily testing conditions throughout several editors (full and inlines) at the same time.

What do you think? Could you check this?

@jbalsas
jbalsas Apr 6, 2013 Adobe Systems Incorporated member

Oops, I didn't see your edited comment.

Is what I just proposed what you had before?

@TomMalbran
TomMalbran Apr 6, 2013 collaborator

Yes, this is one of the way it worked if we want to pass the editor as a parameter. The other option was using a deferred and run the code inside the a done function from the open editor instead of a run.

@jbalsas
jbalsas Apr 6, 2013 Adobe Systems Incorporated member

I think passing the editor as a parameter gives us better control, and keeps the helper methods API clean, but at this point I feel like we're dancing around for some little gain.

What do you think? Do you feel more strongly about some of the other options?

@TomMalbran
TomMalbran Apr 6, 2013 collaborator

The runs would be ok to add to each function. I'll add those.

@TomMalbran
Collaborator

I think passing the editor as a parameter gives us better control, and keeps the helper methods API clean, but at this point I feel like we're dancing around for some little gain.

Done, and since all the test were running a bit slowing as they had to open an close several windows, I managed to make them run all in the same window, which makes it faster and nicer, but let me know if there is any problem with this.

I'm still not happy that strange missing bracket character issue... I'll try to spend some time on if afterwards.

I think the problem here is not with the code but is the fact that the event simulation creates a new event that can be handled with a listener but won't make a key input in a textarea or input field. So the text isn't added to the textarea that CodeMirror uses, but CodeMirror does listen to the event and calls the addon to it's job.

@jbalsas
Member
jbalsas commented Apr 7, 2013

Thanks for working on this. Some of the runs could probably be removed, but we could address that in a later cleanup if desired.

Looks good! Merging.

@jbalsas jbalsas merged commit d2cf66e into adobe:master Apr 7, 2013

1 check passed

Details default The Travis build passed
@TomMalbran
Collaborator

Great, thanks.

Which runs are you referring to? If is the ones that check the current selection, I tried removing them, but couldn't, since it was getting executed before the check functions where run and it then expected 0 to be the given position.

@TomMalbran TomMalbran deleted the TomMalbran:tom/editor-options-tests branch Apr 7, 2013
@jbalsas
Member
jbalsas commented Apr 7, 2013

I was thinking of the ones inside the check... methods, since nothing should have async issues in there anymore, but it's just a minor nit.

@TomMalbran
Collaborator

I see. I am planning on add an option to toggle the auto close tags, and add tests, so I might add it there if everything works without them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment