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