Chromium Code Reviews| Index: dart/tests/try/cursor_position_test.dart |
| diff --git a/dart/tests/try/cursor_position_test.dart b/dart/tests/try/cursor_position_test.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..fc59691e22fb1c660dad5b1571c3aa54d68974ed |
| --- /dev/null |
| +++ b/dart/tests/try/cursor_position_test.dart |
| @@ -0,0 +1,144 @@ |
| +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +// SharedOptions=--package-root=sdk/lib/_internal/ |
| + |
| +// Test that cursor positions are correctly updated after adding new content. |
| + |
| +library trydart.cursor_position_test; |
| + |
| +import 'dart:html'; |
| +import 'dart:async'; |
| + |
| +import '../../site/try/src/interaction_manager.dart' show |
| + InteractionManager; |
| + |
| +import '../../site/try/src/ui.dart' show |
| + hackDiv, |
| + mainEditorPane, |
| + observer; |
| + |
| +import '../../site/try/src/user_option.dart' show |
| + UserOption; |
| + |
| +import '../../pkg/expect/lib/expect.dart'; |
| + |
| +import '../../pkg/async_helper/lib/async_helper.dart'; |
| + |
| +void main() { |
| + InteractionManager interaction = mockTryDartInteraction(); |
| + |
| + List<TestCase> tests = <TestCase>[ |
| + |
| + new TestCase('Test adding two lines programmatically.', () { |
| + clearEditorPaneWithoutNotifications(); |
| + mainEditorPane.appendText('\n\n'); |
| + Text text = mainEditorPane.firstChild; |
| + window.getSelection().collapse(text, 1); |
| + checkSelectionIsCollapsed(text, 1); |
| + }, checkAtBeginningOfSecondLine), |
| + |
| + new TestCase('Test adding a new line with mock key event.', () { |
| + clearEditorPaneWithoutNotifications(); |
| + checkSelectionIsCollapsed(mainEditorPane, 0); |
| + simulateEnterKeyDown(interaction); |
| + }, checkAtBeginningOfSecondLine), |
| + |
| + ]; |
| + |
| + runTests(tests.iterator, completerForAsyncTest()); |
| +} |
| + |
| +void simulateEnterKeyDown(Interaction interaction) { |
| + interaction.onKeyUp( |
| + new MockKeyboardEvent('keydown', keyCode: KeyCode.ENTER)); |
| +} |
| + |
| +void clearEditorPaneWithoutNotifications() { |
| + mainEditorPane.nodes.clear(); |
| + observer.takeRecords(); |
| +} |
| + |
| +void checkSelectionIsCollapsed(Node node, int offset) { |
| + var selection = window.getSelection(); |
| + Expect.isTrue(selection.isCollapsed, 'selection.isCollapsed'); |
| + Expect.equals(node, selection.anchorNode, 'selection.anchorNode'); |
| + Expect.equals(offset, selection.anchorOffset, 'selection.anchorOffset'); |
| +} |
| + |
| +void checkLineCount(int expectedLineCount) { |
| + Expect.equals( |
| + expectedLineCount, mainEditorPane.nodes.length, |
| + 'mainEditorPane.nodes.length'); |
| +} |
| + |
| +void checkAtBeginningOfSecondLine() { |
| + checkLineCount(2); |
| + checkSelectionIsCollapsed(mainEditorPane.nodes[1].firstChild, 0); |
| +} |
| + |
| +runTests(Iterator<TestCase> iterator, Completer completer) { |
| + if (iterator.moveNext()) { |
| + TestCase test = iterator.current; |
| + new Future(() { |
| + print('${test.description}\nSetup.'); |
| + test.setup(); |
| + new Future(() { |
| + test.validate(); |
| + print('${test.description}\nDone.'); |
| + runTests(iterator, completer); |
| + }); |
| + }); |
| + } else { |
| + completer.complete(null); |
| + } |
| +} |
| + |
| +Completer completerForAsyncTest() { |
| + Completer completer = new Completer(); |
| + asyncTest(() => completer.future.then((_) { |
| + // Clear the DOM to work around a bug in test.dart. |
| + document.body.nodes.clear(); |
| + })); |
| + return completer; |
| +} |
| + |
| +InteractionManager mockTryDartInteraction() { |
| + UserOption.storage = {}; |
| + |
| + InteractionManager interaction = new InteractionManager(); |
| + |
| + hackDiv = new DivElement(); |
| + mainEditorPane = new DivElement() |
| + ..style.whiteSpace = 'pre' |
| + ..contentEditable = 'true'; |
| + |
| + observer = new MutationObserver(interaction.onMutation); |
| + observer.observe( |
| + mainEditorPane, childList: true, characterData: true, subtree: true); |
| + |
| + document.body.nodes.addAll([mainEditorPane, hackDiv]); |
| + |
| + return interaction; |
| +} |
| + |
| +class MockKeyboardEvent extends KeyEvent { |
| + final int keyCode; |
| + |
| + MockKeyboardEvent(String type, {int keyCode}) |
| + : this.keyCode = keyCode, |
| + super.wrap(new KeyEvent(type, keyCode: keyCode)); |
| + |
| + bool getModifierState(String keyArgument) => false; |
| +} |
| + |
| +typedef void VoidFunction(); |
|
kasperl
2014/05/06 04:51:06
Is this really so much better than just using Func
ahe
2014/05/06 12:54:02
I don't think Function serves much purpose, and I
|
| + |
| +class TestCase { |
| + final String description; |
| + final VoidFunction setup; |
| + final VoidFunction validate; |
| + |
| + TestCase(this.description, this.setup, this.validate); |
| +} |