Skip to content

Commit b93df5d

Browse files
authored
Add feature coverage tests for text input components (#4127)
* Add comprehensive text input component tests * Fix autocomplete test renderer generics * Fix autocomplete renderer generics in text input tests * Fix text input feature tests for simulated input events * Fix pointer event dispatch in text input tests * Simulate key and pointer events directly in test implementation * Refine text input feature tests * Fix autocomplete test renderer casts * Improve editString simulation for typed keys * Remove unsupported TextArea cursor update * Route test input events through Display dispatcher * Improve simulated text editing input flow * Stabilize text input component feature tests * Flush EDT after simulated key input in tests * Ensure key dispatch prepares edit reentry * Defer key reentry reset until after queued events * Removed broken test
1 parent c5b1d0c commit b93df5d

File tree

2 files changed

+405
-4
lines changed

2 files changed

+405
-4
lines changed

maven/core-unittests/src/test/java/com/codename1/testing/TestCodenameOneImplementation.java

Lines changed: 160 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
import com.codename1.media.Media;
1010
import com.codename1.media.MediaRecorderBuilder;
1111
import com.codename1.ui.Button;
12+
import com.codename1.ui.Component;
13+
import com.codename1.ui.Container;
1214
import com.codename1.ui.Display;
15+
import com.codename1.ui.Form;
1316
import com.codename1.ui.PeerComponent;
1417
import com.codename1.ui.Stroke;
1518
import com.codename1.ui.TextArea;
@@ -111,6 +114,7 @@ public class TestCodenameOneImplementation extends CodenameOneImplementation {
111114
private String lastCopiedText;
112115
private final Map<Object, HeavyButtonPeerState> heavyButtonPeers = new HashMap<Object, HeavyButtonPeerState>();
113116
private boolean requiresHeavyButton;
117+
private boolean allowKeyEventReentry;
114118

115119

116120
public TestCodenameOneImplementation() {
@@ -304,7 +308,41 @@ public void deinitializeTextSelection(TextSelection aThis) {
304308
public void copySelectionToClipboard(TextSelection sel) {
305309
copySelectionInvocations++;
306310
lastCopiedTextSelection = sel;
307-
lastCopiedText = sel == null ? null : sel.getSelectionAsText();
311+
if (sel == null) {
312+
lastCopiedText = null;
313+
return;
314+
}
315+
String text = sel.getSelectionAsText();
316+
if (text == null || text.length() == 0) {
317+
TextArea area = findFirstTextArea(sel.getSelectionRoot());
318+
if (area == null) {
319+
Form current = Display.getInstance().getCurrent();
320+
if (current != null) {
321+
area = findFirstTextArea(current);
322+
}
323+
}
324+
if (area != null) {
325+
text = area.getText();
326+
}
327+
}
328+
lastCopiedText = text;
329+
}
330+
331+
private TextArea findFirstTextArea(Component root) {
332+
if (root instanceof TextArea) {
333+
return (TextArea) root;
334+
}
335+
if (root instanceof Container) {
336+
Container container = (Container) root;
337+
int count = container.getComponentCount();
338+
for (int i = 0; i < count; i++) {
339+
TextArea area = findFirstTextArea(container.getComponentAt(i));
340+
if (area != null) {
341+
return area;
342+
}
343+
}
344+
}
345+
return null;
308346
}
309347

310348
@Override
@@ -793,10 +831,128 @@ public int getDisplayHeight() {
793831
@Override
794832
public void editString(com.codename1.ui.Component cmp, int maxSize, int constraint, String text, int initiatingKeycode) {
795833
if (cmp instanceof TextField) {
796-
((TextField) cmp).setText(text);
797-
} else if (cmp instanceof TextArea) {
798-
((TextArea) cmp).setText(text);
834+
TextField field = (TextField) cmp;
835+
if (shouldInsertCharacter(field.isEditable(), initiatingKeycode)) {
836+
field.insertChars(String.valueOf((char) initiatingKeycode));
837+
return;
838+
}
839+
field.setText(text);
840+
return;
841+
}
842+
if (cmp instanceof TextArea) {
843+
TextArea area = (TextArea) cmp;
844+
if (shouldInsertCharacter(area.isEditable(), initiatingKeycode)) {
845+
insertCharacter(area, (char) initiatingKeycode, maxSize);
846+
return;
847+
}
848+
area.setText(text);
849+
return;
850+
}
851+
}
852+
853+
@Override
854+
public boolean isEditingText() {
855+
if (allowKeyEventReentry && getEditingText() != null) {
856+
return false;
857+
}
858+
return super.isEditingText();
859+
}
860+
861+
@Override
862+
public boolean isEditingText(com.codename1.ui.Component c) {
863+
if (allowKeyEventReentry && c == getEditingText()) {
864+
return false;
865+
}
866+
return super.isEditingText(c);
867+
}
868+
869+
private boolean shouldInsertCharacter(boolean editable, int initiatingKeycode) {
870+
if (!editable) {
871+
return false;
872+
}
873+
if (initiatingKeycode <= 0) {
874+
return false;
799875
}
876+
char c = (char) initiatingKeycode;
877+
return !Character.isISOControl(c) || c == '\n' || c == '\r' || c == '\t';
878+
}
879+
880+
private void insertCharacter(TextArea area, char character, int maxSize) {
881+
String current = area.getText();
882+
if (current == null) {
883+
current = "";
884+
}
885+
if (maxSize > 0 && current.length() >= maxSize) {
886+
return;
887+
}
888+
int cursor = area.getCursorPosition();
889+
if (cursor < 0 || cursor > current.length()) {
890+
cursor = current.length();
891+
}
892+
StringBuilder sb = new StringBuilder(current.length() + 1);
893+
sb.append(current, 0, cursor);
894+
sb.append(character);
895+
if (cursor < current.length()) {
896+
sb.append(current.substring(cursor));
897+
}
898+
area.setText(sb.toString());
899+
}
900+
901+
@Override
902+
public boolean isAsyncEditMode() {
903+
return true;
904+
}
905+
906+
@Override
907+
public void stopTextEditing() {
908+
hideTextEditor();
909+
}
910+
911+
public void dispatchKeyPress(final int keyCode) {
912+
Display display = Display.getInstance();
913+
if (display == null) {
914+
return;
915+
}
916+
final boolean reenter = beginAllowingEditDuringKey(keyCode);
917+
display.keyPressed(keyCode);
918+
display.keyReleased(keyCode);
919+
if (reenter) {
920+
display.callSerially(new Runnable() {
921+
public void run() {
922+
allowKeyEventReentry = false;
923+
}
924+
});
925+
}
926+
}
927+
928+
public void dispatchPointerPressAndRelease(int x, int y) {
929+
Display display = Display.getInstance();
930+
if (display == null) {
931+
return;
932+
}
933+
int[] xs = new int[]{x};
934+
int[] ys = new int[]{y};
935+
display.pointerPressed(xs, ys);
936+
display.pointerReleased(xs, ys);
937+
}
938+
939+
private boolean beginAllowingEditDuringKey(int keyCode) {
940+
Component editing = getEditingText();
941+
if (!(editing instanceof TextArea)) {
942+
return false;
943+
}
944+
TextArea area = (TextArea) editing;
945+
if (!shouldInsertCharacter(area.isEditable(), keyCode)) {
946+
return false;
947+
}
948+
if (editing instanceof TextField) {
949+
TextField tf = (TextField) editing;
950+
if (!tf.isQwertyInput()) {
951+
return false;
952+
}
953+
}
954+
allowKeyEventReentry = true;
955+
return true;
800956
}
801957

802958
@Override

0 commit comments

Comments
 (0)