Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp

Issue 2493703002: Make "compositionend" event fired after setting caret position (Closed)
Patch Set: Add more test. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/editing/InputMethodController.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/editing/InputMethodController.h" 5 #include "core/editing/InputMethodController.h"
6 6
7 #include "core/dom/Document.h" 7 #include "core/dom/Document.h"
8 #include "core/dom/Element.h" 8 #include "core/dom/Element.h"
9 #include "core/dom/Range.h" 9 #include "core/dom/Range.h"
10 #include "core/editing/Editor.h" 10 #include "core/editing/Editor.h"
(...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 EXPECT_EQ(3u, controller().getSelectionOffsets().end()); 804 EXPECT_EQ(3u, controller().getSelectionOffsets().end());
805 } 805 }
806 806
807 TEST_F(InputMethodControllerTest, CompositionInputEventIsComposing) { 807 TEST_F(InputMethodControllerTest, CompositionInputEventIsComposing) {
808 document().settings()->setScriptEnabled(true); 808 document().settings()->setScriptEnabled(true);
809 Element* editable = insertHTMLElement( 809 Element* editable = insertHTMLElement(
810 "<div id='sample' contentEditable='true'></div>", "sample"); 810 "<div id='sample' contentEditable='true'></div>", "sample");
811 Element* script = document().createElement("script", ASSERT_NO_EXCEPTION); 811 Element* script = document().createElement("script", ASSERT_NO_EXCEPTION);
812 script->setInnerHTML( 812 script->setInnerHTML(
813 "document.getElementById('sample').addEventListener('beforeinput', " 813 "document.getElementById('sample').addEventListener('beforeinput', "
814 "function(event) {" 814 "event => {"
815 " document.title = `beforeinput.isComposing:${event.isComposing};`;" 815 " document.title = `beforeinput.isComposing:${event.isComposing};`;"
816 "});" 816 "});"
817 "document.getElementById('sample').addEventListener('input', " 817 "document.getElementById('sample').addEventListener('input', "
818 "function(event) {" 818 "event => {"
819 " document.title += `input.isComposing:${event.isComposing};`;" 819 " document.title += `input.isComposing:${event.isComposing};`;"
820 "});", 820 "});",
821 ASSERT_NO_EXCEPTION); 821 ASSERT_NO_EXCEPTION);
822 document().body()->appendChild(script, ASSERT_NO_EXCEPTION); 822 document().body()->appendChild(script, ASSERT_NO_EXCEPTION);
823 document().view()->updateAllLifecyclePhases(); 823 document().view()->updateAllLifecyclePhases();
824 824
825 // Simulate composition in the |contentEditable|. 825 // Simulate composition in the |contentEditable|.
826 Vector<CompositionUnderline> underlines; 826 Vector<CompositionUnderline> underlines;
827 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); 827 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
828 editable->focus(); 828 editable->focus();
829 829
830 document().setTitle(emptyString()); 830 document().setTitle(emptyString());
831 controller().setComposition("foo", underlines, 0, 3); 831 controller().setComposition("foo", underlines, 0, 3);
832 EXPECT_STREQ("beforeinput.isComposing:true;input.isComposing:true;", 832 EXPECT_STREQ("beforeinput.isComposing:true;input.isComposing:true;",
833 document().title().utf8().data()); 833 document().title().utf8().data());
834 834
835 document().setTitle(emptyString()); 835 document().setTitle(emptyString());
836 controller().finishComposingText(InputMethodController::KeepSelection); 836 controller().finishComposingText(InputMethodController::KeepSelection);
837 // Last pair of InputEvent should also be inside composition scope. 837 // Last pair of InputEvent should also be inside composition scope.
838 EXPECT_STREQ("beforeinput.isComposing:true;input.isComposing:true;", 838 EXPECT_STREQ("beforeinput.isComposing:true;input.isComposing:true;",
839 document().title().utf8().data()); 839 document().title().utf8().data());
840 } 840 }
841 841
842 TEST_F(InputMethodControllerTest, CompositionInputEventData) { 842 TEST_F(InputMethodControllerTest, CompositionInputEventForReplace) {
yosin_UTC9 2016/11/17 01:39:55 Could you make another CL for re-factoring IMCTest
yabinh 2016/11/17 05:15:54 Done.
843 document().settings()->setScriptEnabled(true); 843 document().settings()->setScriptEnabled(true);
844 Element* editable = insertHTMLElement( 844 Element* editable = insertHTMLElement(
845 "<div id='sample' contentEditable='true'></div>", "sample"); 845 "<div id='sample' contentEditable='true'></div>", "sample");
yosin_UTC9 2016/11/17 01:39:55 nit: s/contentEditable='true'/contenteditable/
yabinh 2016/11/17 05:15:55 Done. Also applied to other places.
846 Element* script = document().createElement("script", ASSERT_NO_EXCEPTION); 846 Element* script = document().createElement("script", ASSERT_NO_EXCEPTION);
847 script->setInnerHTML( 847 script->setInnerHTML(
848 "document.getElementById('sample').addEventListener('beforeinput', " 848 "document.getElementById('sample').addEventListener('beforeinput', "
849 "function(event) {" 849 "event => {"
yosin_UTC9 2016/11/17 01:39:55 nit: You can write this in one line: event => doc
yabinh 2016/11/17 05:15:55 Done.
850 " document.title = `beforeinput.data:${event.data};`;" 850 " document.title = `beforeinput.data:${event.data};`;"
851 "});" 851 "});"
852 "document.getElementById('sample').addEventListener('input', " 852 "document.getElementById('sample').addEventListener('input', "
853 "function(event) {" 853 "event => {"
854 " document.title += `input.data:${event.data};`;" 854 " document.title += `input.data:${event.data};`;"
855 "});"
856 "document.getElementById('sample').addEventListener('compositionend', "
857 "event => {"
858 " document.title += `compositionend.data:${event.data};`;"
855 "});", 859 "});",
856 ASSERT_NO_EXCEPTION); 860 ASSERT_NO_EXCEPTION);
857 document().body()->appendChild(script, ASSERT_NO_EXCEPTION); 861 document().body()->appendChild(script, ASSERT_NO_EXCEPTION);
858 document().view()->updateAllLifecyclePhases(); 862 document().view()->updateAllLifecyclePhases();
859 863
860 // Simulate composition in the |contentEditable|. 864 // Simulate composition in the |contentEditable|.
861 Vector<CompositionUnderline> underlines; 865 Vector<CompositionUnderline> underlines;
862 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); 866 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
863 editable->focus(); 867 editable->focus();
864 868
865 document().setTitle(emptyString()); 869 document().setTitle(emptyString());
866 controller().setComposition("n", underlines, 0, 1); 870 controller().setComposition("hell", underlines, 4, 4);
871 EXPECT_STREQ("beforeinput.data:hell;input.data:hell;",
872 document().title().utf8().data());
873
874 // Replace the existing composition.
875 // TODO(yabinh): should be "beforeinput.data:hello;input.data:hello;".
876 document().setTitle(emptyString());
877 controller().setComposition("hello", underlines, 0, 0);
878 EXPECT_STREQ("beforeinput.data:o;input.data:o;",
879 document().title().utf8().data());
880 }
881
882 TEST_F(InputMethodControllerTest, CompositionInputEventForConfirm) {
883 document().settings()->setScriptEnabled(true);
884 Element* editable = insertHTMLElement(
885 "<div id='sample' contentEditable='true'></div>", "sample");
886 Element* script = document().createElement("script", ASSERT_NO_EXCEPTION);
yosin_UTC9 2016/11/17 01:39:55 nit: No need to have |ASSERT_NO_EXCEPTION|
yabinh 2016/11/17 05:15:54 Done.
887 script->setInnerHTML(
888 "document.getElementById('sample').addEventListener('beforeinput', "
889 "event => {"
890 " document.title = `beforeinput.data:${event.data};`;"
891 "});"
892 "document.getElementById('sample').addEventListener('input', "
893 "event => {"
894 " document.title += `input.data:${event.data};`;"
895 "});"
896 "document.getElementById('sample').addEventListener('compositionend', "
897 "event => {"
898 " document.title += `compositionend.data:${event.data};`;"
899 "});",
900 ASSERT_NO_EXCEPTION);
yosin_UTC9 2016/11/17 01:39:55 Note: I'm going to make |ASSERT_NO_EXCPETION| in |
yabinh 2016/11/17 05:15:54 Done.
901 document().body()->appendChild(script, ASSERT_NO_EXCEPTION);
902 document().view()->updateAllLifecyclePhases();
yosin_UTC9 2016/11/17 01:39:55 nit: No need to have |ASSERT_NO_EXCEPTION|
yabinh 2016/11/17 05:15:54 Done.
903
904 // Simulate composition in the |contentEditable|.
905 Vector<CompositionUnderline> underlines;
906 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
907 editable->focus();
908
909 document().setTitle(emptyString());
910 controller().setComposition("hello", underlines, 5, 5);
911 EXPECT_STREQ("beforeinput.data:hello;input.data:hello;",
912 document().title().utf8().data());
913
914 // Confirm the ongoing composition.
915 document().setTitle(emptyString());
916 controller().finishComposingText(InputMethodController::KeepSelection);
917 EXPECT_STREQ(
918 "beforeinput.data:hello;input.data:hello;compositionend.data:hello;",
919 document().title().utf8().data());
920 }
921
922 TEST_F(InputMethodControllerTest, CompositionInputEventForDelete) {
923 document().settings()->setScriptEnabled(true);
924 Element* editable = insertHTMLElement(
925 "<div id='sample' contentEditable='true'></div>", "sample");
926 Element* script = document().createElement("script", ASSERT_NO_EXCEPTION);
yosin_UTC9 2016/11/17 01:39:55 nit: No need to have |ASSERT_NO_EXCEPTION|
yabinh 2016/11/17 05:15:54 Done.
927 script->setInnerHTML(
928 "document.getElementById('sample').addEventListener('beforeinput', "
929 "event => {"
930 " document.title = `beforeinput.data:${event.data};`;"
931 "});"
932 "document.getElementById('sample').addEventListener('input', "
933 "event => {"
934 " document.title += `input.data:${event.data};`;"
935 "});"
936 "document.getElementById('sample').addEventListener('compositionend', "
937 "event => {"
938 " document.title += `compositionend.data:${event.data};`;"
939 "});",
940 ASSERT_NO_EXCEPTION);
941 document().body()->appendChild(script, ASSERT_NO_EXCEPTION);
yosin_UTC9 2016/11/17 01:39:55 nit: No need to have |ASSERT_NO_EXCEPTION|
yabinh 2016/11/17 05:15:54 Done.
942 document().view()->updateAllLifecyclePhases();
943
944 // Simulate composition in the |contentEditable|.
945 Vector<CompositionUnderline> underlines;
946 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
947 editable->focus();
948
949 document().setTitle(emptyString());
950 controller().setComposition("hello", underlines, 5, 5);
951 EXPECT_STREQ("beforeinput.data:hello;input.data:hello;",
952 document().title().utf8().data());
953
954 // Delete the existing composition.
955 document().setTitle(emptyString());
956 controller().setComposition("", underlines, 0, 0);
957 EXPECT_STREQ("beforeinput.data:;compositionend.data:;",
958 document().title().utf8().data());
959 }
960
961 TEST_F(InputMethodControllerTest, CompositionInputEventForInsert) {
962 document().settings()->setScriptEnabled(true);
963 Element* editable = insertHTMLElement(
964 "<div id='sample' contentEditable='true'></div>", "sample");
965 Element* script = document().createElement("script", ASSERT_NO_EXCEPTION);
yosin_UTC9 2016/11/17 01:39:55 nit: No need to have |ASSERT_NO_EXCEPTION|
yabinh 2016/11/17 05:15:54 Done.
966 script->setInnerHTML(
967 "document.getElementById('sample').addEventListener('beforeinput', "
968 "event => {"
969 " document.title = `beforeinput.data:${event.data};`;"
970 "});"
971 "document.getElementById('sample').addEventListener('input', "
972 "event => {"
973 " document.title += `input.data:${event.data};`;"
974 "});"
975 "document.getElementById('sample').addEventListener('compositionend', "
976 "event => {"
977 " document.title += `compositionend.data:${event.data};`;"
978 "});",
979 ASSERT_NO_EXCEPTION);
980 document().body()->appendChild(script, ASSERT_NO_EXCEPTION);
981 document().view()->updateAllLifecyclePhases();
982
983 // Simulate composition in the |contentEditable|.
984 Vector<CompositionUnderline> underlines;
985 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
986 editable->focus();
987
988 // Insert new text without previous composition.
989 document().setTitle(emptyString());
990 document().updateStyleAndLayout();
991 controller().commitText("hello", 0);
992 EXPECT_STREQ("beforeinput.data:hello;input.data:hello;",
993 document().title().utf8().data());
994
995 document().setTitle(emptyString());
996 controller().setComposition("n", underlines, 1, 1);
867 EXPECT_STREQ("beforeinput.data:n;input.data:n;", 997 EXPECT_STREQ("beforeinput.data:n;input.data:n;",
868 document().title().utf8().data()); 998 document().title().utf8().data());
869 999
870 document().setTitle(emptyString()); 1000 // Insert new text with previous composition.
871 controller().setComposition("ni", underlines, 0, 1); 1001 document().setTitle(emptyString());
872 EXPECT_STREQ("beforeinput.data:i;input.data:i;", 1002 document().updateStyleAndLayout();
873 document().title().utf8().data()); 1003 controller().commitText("hello", 1);
874 1004 EXPECT_STREQ(
875 document().setTitle(emptyString()); 1005 "beforeinput.data:hello;input.data:hello;compositionend.data:hello;",
876 controller().finishComposingText(InputMethodController::KeepSelection); 1006 document().title().utf8().data());
877 EXPECT_STREQ("beforeinput.data:ni;input.data:ni;", 1007 }
878 document().title().utf8().data()); 1008
1009 TEST_F(InputMethodControllerTest, CompositionEndEventForConfirm) {
1010 document().settings()->setScriptEnabled(true);
1011 Element* editable = insertHTMLElement(
1012 "<div id='sample' contentEditable='true'></div>", "sample");
1013 Element* script = document().createElement("script", ASSERT_NO_EXCEPTION);
1014 script->setInnerHTML(
1015 "document.getElementById('sample').addEventListener('compositionend', "
1016 "event => {"
1017 // If the caret position is set before firing 'compositonend' event (and
1018 // it should), the final caret position will be reset to [3,3].
1019 " const node = document.getElementById('sample').firstChild;"
1020 " getSelection().collapse(node, 3);"
1021 "});",
1022 ASSERT_NO_EXCEPTION);
1023 document().body()->appendChild(script, ASSERT_NO_EXCEPTION);
1024 document().view()->updateAllLifecyclePhases();
1025
1026 // Simulate composition in the |contentEditable|.
1027 Vector<CompositionUnderline> underlines;
1028 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
1029 editable->focus();
1030
1031 controller().setComposition("hello", underlines, 1, 1);
1032 document().updateStyleAndLayout();
1033 EXPECT_EQ(1u, controller().getSelectionOffsets().start());
1034 EXPECT_EQ(1u, controller().getSelectionOffsets().end());
1035
1036 // Confirm the ongoing composition. Note that it moves the caret to the end of
1037 // text [5,5] before firing 'compositonend' event.
1038 controller().finishComposingText(InputMethodController::DoNotKeepSelection);
1039 document().updateStyleAndLayout();
1040 EXPECT_EQ(3u, controller().getSelectionOffsets().start());
1041 EXPECT_EQ(3u, controller().getSelectionOffsets().end());
1042 }
1043
1044 TEST_F(InputMethodControllerTest, CompositionEndEventForInsert) {
1045 document().settings()->setScriptEnabled(true);
1046 Element* editable = insertHTMLElement(
1047 "<div id='sample' contentEditable='true'></div>", "sample");
1048 Element* script = document().createElement("script", ASSERT_NO_EXCEPTION);
yosin_UTC9 2016/11/17 01:39:55 nit: No need to have |ASSERT_NO_EXCEPTION|
yabinh 2016/11/17 05:15:54 Done.
1049 script->setInnerHTML(
1050 "document.getElementById('sample').addEventListener('compositionend', "
1051 "event => {"
1052 // If the caret position is set before firing 'compositonend' event (and
1053 // it should), the final caret position will be reset to [3,3].
1054 " const node = document.getElementById('sample').firstChild;"
1055 " getSelection().collapse(node, 3);"
1056 "});",
1057 ASSERT_NO_EXCEPTION);
1058 document().body()->appendChild(script, ASSERT_NO_EXCEPTION);
1059 document().view()->updateAllLifecyclePhases();
1060
1061 // Simulate composition in the |contentEditable|.
1062 Vector<CompositionUnderline> underlines;
1063 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
1064 editable->focus();
1065
1066 controller().setComposition("n", underlines, 1, 1);
1067
1068 // Insert new text with previous composition. Note that it moves the caret to
1069 // [4,4] before firing 'compositonend' event.
1070 document().updateStyleAndLayout();
1071 controller().commitText("hello", -1);
1072 document().updateStyleAndLayout();
1073 EXPECT_EQ(3u, controller().getSelectionOffsets().start());
1074 EXPECT_EQ(3u, controller().getSelectionOffsets().end());
1075 }
1076
1077 TEST_F(InputMethodControllerTest, CompositionEndEventWithRangeSelection) {
1078 document().settings()->setScriptEnabled(true);
1079 Element* editable = insertHTMLElement(
1080 "<div id='sample' contentEditable='true'></div>", "sample");
1081 Element* script = document().createElement("script", ASSERT_NO_EXCEPTION);
yosin_UTC9 2016/11/17 01:39:55 nit: No need to have |ASSERT_NO_EXCEPTION|
yabinh 2016/11/17 05:15:55 Done.
1082 script->setInnerHTML(
1083 "document.getElementById('sample').addEventListener('compositionend', "
1084 "event => {"
1085 // If the caret position is set before firing 'compositonend' event (and
1086 // it should), the final caret position will be reset to [2,4].
1087 " const node = document.getElementById('sample').firstChild;"
1088 " var range = document.createRange();"
1089 " range.setStart(node, 2);"
1090 " range.setEnd(node, 4);"
1091 " const selection = getSelection();"
1092 " selection.removeAllRanges();"
1093 " selection.addRange(range);"
1094 "});",
1095 ASSERT_NO_EXCEPTION);
1096 document().body()->appendChild(script, ASSERT_NO_EXCEPTION);
1097 document().view()->updateAllLifecyclePhases();
1098
1099 // Simulate composition in the |contentEditable|.
1100 Vector<CompositionUnderline> underlines;
1101 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
1102 editable->focus();
1103
1104 controller().setComposition("hello", underlines, 1, 1);
1105 document().updateStyleAndLayout();
1106 EXPECT_EQ(1u, controller().getSelectionOffsets().start());
1107 EXPECT_EQ(1u, controller().getSelectionOffsets().end());
1108
1109 // Confirm the ongoing composition. Note that it moves the caret to the end of
1110 // text [5,5] before firing 'compositonend' event.
1111 controller().finishComposingText(InputMethodController::DoNotKeepSelection);
1112 document().updateStyleAndLayout();
1113 EXPECT_EQ(2u, controller().getSelectionOffsets().start());
1114 EXPECT_EQ(4u, controller().getSelectionOffsets().end());
1115 }
1116
1117 TEST_F(InputMethodControllerTest, CompositionEndEventWithNoneSelection) {
1118 document().settings()->setScriptEnabled(true);
1119 Element* editable = insertHTMLElement(
1120 "<div id='sample' contentEditable='true'></div>", "sample");
1121 Element* script = document().createElement("script", ASSERT_NO_EXCEPTION);
yosin_UTC9 2016/11/17 01:39:55 nit: No need to have |ASSERT_NO_EXCEPTION|
yabinh 2016/11/17 05:15:54 Done.
1122 script->setInnerHTML(
1123 "document.getElementById('sample').addEventListener('compositionend', "
1124 "event => {"
1125 // If the caret position is set before firing 'compositonend' event (and
1126 // it should), the final caret position will be reset to null.
1127 " getSelection().removeAllRanges();"
1128 "});",
1129 ASSERT_NO_EXCEPTION);
1130 document().body()->appendChild(script, ASSERT_NO_EXCEPTION);
1131 document().view()->updateAllLifecyclePhases();
1132
1133 // Simulate composition in the |contentEditable|.
1134 Vector<CompositionUnderline> underlines;
1135 underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
1136 editable->focus();
1137
1138 controller().setComposition("hello", underlines, 1, 1);
1139 document().updateStyleAndLayout();
1140 EXPECT_EQ(1u, controller().getSelectionOffsets().start());
1141 EXPECT_EQ(1u, controller().getSelectionOffsets().end());
1142
1143 // Confirm the ongoing composition. Note that it moves the caret to the end of
1144 // text [5,5] before firing 'compositonend' event.
1145 controller().finishComposingText(InputMethodController::DoNotKeepSelection);
1146 document().updateStyleAndLayout();
1147 EXPECT_TRUE(controller().getSelectionOffsets().isNull());
879 } 1148 }
880 1149
881 } // namespace blink 1150 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/editing/InputMethodController.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698