I have enjoyed refactoring my ICE Code Editor tests over the last few days. I have an even better understanding of how to test in Dart and how to make those tests as readable and robust as possible. I am sorely tempted to continue mucking about with the test suite itself, but the most pressing issue that I need to answer tonight is an actual feature. More specifically, I need to figure out how to test when different pieces of ICE are visible.
One of the few remaining issues in the so-called 3D Game Programming for Kids milestone is giving ICE focus after dialogs and menus have closed. Since the milestone gets its name because it is blocking a release for the 3D Game Programming for Kids book, it seems worth making it a priority.
I need to start by adding a feature to the core
Editor
class, which is responsible for synchronizing the ACE code editor with a preview layer for the visualizations. Currently, there is no way to focus anything in the core editor, so I need to drive that feature. I start with the setup for the new focus group in the
editor_test.dart
file: group("focus", (){
var editor;
setUp((){
document.body.nodes.
add(new Element.html('<div id=ice-${currentTestCase.id}>'));
editor = new Editor(
'#ice-${currentTestCase.id}',
enable_javascript_mode: false
);
return editor.editorReady;
});
// Test will go here...
});
Since this is a core editor test, I have to manually create a <div>
to hold the editor. In the full-screen class, this is done automatically, but this is a lower level test, hence the greater manual effort. I add the editor to that element and return a future as I learned last night.With that, I am ready to test. The first test simply verifies default state—that the code editor is visible:
test('code is visibile by default', (){
var el = document.
query('#ice-${currentTestCase.id}').
query('.ice-code-editor-editor');
expect(el.style.visibility, isNot('hidden'));
});
After some debate, we opted to hide the code editor with CSS visibility rather than via z-index hackery of setting the display to none. I am still not sold on this, but it does make this test easy. And, not unexpectedly, this test passes. In fact, all of the tests for the low-level editor pass. The focus seems to naturally go to the correct location. Well, that and it seems that I had inadvertently copied some focus code from the JavaScript version when I was first getting started on the Dart version: showCode() {
_editor_el.style.visibility = 'visible';
query('.ace_print-margin').style.visibility = 'visible';
_ace.renderer.onResize();
_ace.focus();
}
(again ACE is the actual code editor piece of ICE, which is incorporated via #pairwithme js-interop)Once I am done with the core editor, I work my way out to the Full screen IDE-lite class,
Full
. That actually works as well except in the case in which the code is edited, then hidden before the preview layer has a chance to update itself. Immediately after the code is hidden, the preview has focus, but the updated iframe is enough to lose focus.I drive the test as usual:
solo_group("Focus", (){
var editor;
setUp((){
editor = new Full(enable_javascript_mode: false)
..store.storage_key = "ice-test-${currentTestCase.id}";
var preview_ready = new Completer();
editor.onPreviewChange.listen((e){
if (preview_ready.isCompleted) return;
preview_ready.complete();
});
return preview_ready.future;
});
// tests here
});
But, instead of writing a test, I add another group with more async setup (I really love that newly discovered feature): group("hiding code after update", (){
setUp((){
editor.ice.focus();
editor.content = '<h1>Force Update</h1>';
helpers.click('button', text: 'Hide Code');
var preview_ready = new Completer();
editor.onPreviewChange.listen((e){
preview_ready.complete();
});
return preview_ready.future;
});
test("preview has focus", (){
var el = document.query('iframe');
expect(document.activeElement, el);
});
});
Making that pass is a simple matter of adding a discrete focus()
call.In the end it is a lot of work to verify that most everything is working as desired. Still, it is worth the trouble to have the assurance of a stronger test suite.
I end the night by driving the feature that started this adventure
test("editor has focus after closing a dialog", (){
helpers.click('button', text: '☰');
helpers.click('li', text: 'Make a Copy');
helpers.hitEscape();
var el = document.
query('.ice-code-editor-editor').
query('textarea.ace_text-input');
expect(document.activeElement, el);
});
That gets met the expected error:ERROR: Focus editor has focus after closing a dialog Focus editor has focus after closing a dialog: Test setup failed: Expected: TextAreaElement:<textarea> But: was BodyElement:<body>.That may end up being a little trickier than expected since the menu options lack direct access to ICE to manipulate focus. I think it best to leave that for tomorrow. I always appreciate being able to start work with a failing test. It makes it so easy to jump right in.
Day #784
No comments:
Post a Comment