@@ -21,7 +21,16 @@ QUnit.testStart(() => {
2121 $ ( '#qunit-fixture' ) . html ( '<div id=\'dateBox\'></div>' ) ;
2222} ) ;
2323
24- const simulateIMEInput = function ( eventsData ) {
24+ const insertNativeText = ( $input , text ) => {
25+ const input = $input . get ( 0 ) ;
26+ const start = input . selectionStart || input . value . length ;
27+ const end = input . selectionEnd || start ;
28+
29+ input . value = input . value . slice ( 0 , start ) + text + input . value . slice ( end ) ;
30+ input . setSelectionRange ( start + text . length , start + text . length ) ;
31+ } ;
32+
33+ const simulateIMEInput = function ( eventsData , shouldFireInsertText ) {
2534 this . $input . trigger ( $ . Event ( 'keydown' , {
2635 key : 'Process' ,
2736 code : eventsData . keyDownCode ,
@@ -57,6 +66,28 @@ const simulateIMEInput = function(eventsData) {
5766 } ) ) ;
5867
5968 this . $input . trigger ( $ . Event ( 'compositionend' ) ) ;
69+
70+ if ( shouldFireInsertText ) {
71+ insertNativeText ( this . $input , eventsData . inputData ) ;
72+
73+ this . $input . trigger ( $ . Event ( 'input' , {
74+ type : 'input' ,
75+ originalEvent : $ . Event ( 'input' , {
76+ inputType : 'insertText' ,
77+ isComposing : false ,
78+ data : eventsData . inputData ,
79+ } ) ,
80+ } ) ) ;
81+
82+ this . $input . trigger ( $ . Event ( 'keyup' , {
83+ key : eventsData . inputData ,
84+ code : eventsData . keyDownCode ,
85+ originalEvent : $ . Event ( 'keyup' , {
86+ key : eventsData . inputData ,
87+ code : eventsData . keyDownCode ,
88+ } ) ,
89+ } ) ) ;
90+ }
6091} ;
6192
6293const setupModule = {
@@ -1241,6 +1272,78 @@ module('Search', setupModule, () => {
12411272 assert . strictEqual ( this . $input . val ( ) , '5555/05/05' , 'year was changed' ) ;
12421273 } ) ;
12431274
1275+ test ( 'Typing digits via Numpad IME with final insertText should process every composition cycle once (T1326628)' , function ( assert ) {
1276+ this . instance . option ( {
1277+ displayFormat : 'MM/dd/yyyy' ,
1278+ value : new Date ( 2025 , 9 , 16 ) ,
1279+ } ) ;
1280+
1281+ this . keyboard . caret ( { start : 0 , end : 2 } ) ;
1282+
1283+ const eventsData = {
1284+ keyDownCode : 'Numpad1' ,
1285+ inputData : '1' ,
1286+ } ;
1287+
1288+ simulateIMEInput . call ( this , eventsData , true ) ;
1289+ assert . strictEqual ( this . $input . val ( ) , '01/16/2025' , 'first month digit is applied' ) ;
1290+
1291+ simulateIMEInput . call ( this , eventsData , true ) ;
1292+ assert . strictEqual ( this . $input . val ( ) , '11/16/2025' , 'second month digit is applied' ) ;
1293+
1294+ simulateIMEInput . call ( this , eventsData , true ) ;
1295+ assert . strictEqual ( this . $input . val ( ) , '11/01/2025' , 'first day digit is applied' ) ;
1296+
1297+ simulateIMEInput . call ( this , eventsData , true ) ;
1298+ assert . strictEqual ( this . $input . val ( ) , '11/11/2025' , 'second day digit is applied' ) ;
1299+
1300+ simulateIMEInput . call ( this , eventsData , true ) ;
1301+ assert . strictEqual ( this . $input . val ( ) , '11/11/2021' , 'first year digit is applied' ) ;
1302+
1303+ simulateIMEInput . call ( this , eventsData , true ) ;
1304+ assert . strictEqual ( this . $input . val ( ) , '11/11/2011' , 'second year digit is applied' ) ;
1305+
1306+ simulateIMEInput . call ( this , eventsData , true ) ;
1307+ assert . strictEqual ( this . $input . val ( ) , '11/11/2111' , 'third year digit is applied' ) ;
1308+
1309+ simulateIMEInput . call ( this , eventsData , true ) ;
1310+ assert . strictEqual ( this . $input . val ( ) , '11/11/1111' , 'fourth year digit is applied' ) ;
1311+ } ) ;
1312+
1313+ test ( 'Final insertText after Numpad IME composition should not duplicate digit or corrupt mask value (T1326628)' , function ( assert ) {
1314+ this . instance . option ( {
1315+ displayFormat : 'MM/dd/yyyy' ,
1316+ value : new Date ( 2025 , 9 , 16 ) ,
1317+ } ) ;
1318+
1319+ this . keyboard . caret ( { start : 0 , end : 2 } ) ;
1320+
1321+ simulateIMEInput . call ( this , {
1322+ keyDownCode : 'Numpad1' ,
1323+ inputData : '1' ,
1324+ } , true ) ;
1325+
1326+ simulateIMEInput . call ( this , {
1327+ keyDownCode : 'Numpad1' ,
1328+ inputData : '1' ,
1329+ } , true ) ;
1330+
1331+ assert . strictEqual ( this . $input . val ( ) , '11/16/2025' , 'final insertText commit is ignored as duplicate IME commit' ) ;
1332+ } ) ;
1333+
1334+ test ( 'Typing zero via Numpad IME composition with final insertText should be registered (T1326628)' , function ( assert ) {
1335+ this . instance . option ( {
1336+ displayFormat : 'MM/dd/yyyy' ,
1337+ value : new Date ( 2012 , 8 , 5 ) ,
1338+ } ) ;
1339+
1340+ this . keyboard . caret ( { start : 0 , end : 2 } ) ;
1341+
1342+ simulateIMEInput . call ( this , { keyDownCode : 'Numpad1' , inputData : '1' } , true ) ;
1343+ simulateIMEInput . call ( this , { keyDownCode : 'Numpad0' , inputData : '0' } , true ) ;
1344+
1345+ assert . strictEqual ( this . $input . val ( ) , '10/05/2012' , 'month is correctly set to 10 after typing "1" then "0" via Numpad IME' ) ;
1346+ } ) ;
12441347
12451348 test ( 'Pasting incorrect value to the date part should not ignore mask rules' , function ( assert ) {
12461349 this . instance . option ( 'displayFormat' , 'yyyy/MM/dd' ) ;
0 commit comments