diff --git a/projects/demo-integrations/src/tests/kit/date-time/date-time-meridiem.cy.ts b/projects/demo-integrations/src/tests/kit/date-time/date-time-meridiem.cy.ts index 0ac586a80..2a8697174 100644 --- a/projects/demo-integrations/src/tests/kit/date-time/date-time-meridiem.cy.ts +++ b/projects/demo-integrations/src/tests/kit/date-time/date-time-meridiem.cy.ts @@ -267,27 +267,27 @@ describe('DateTime | time modes with meridiem', () => { }); describe('toggle meridiem value on ArrowUp / ArrowDown', () => { - describe('Initial value === "12:34|"', () => { - const beforeMeridiemValue = '01.01.2000, 12:34'; + describe('Initial value === "12:34 |"', () => { + const beforeMeridiemValue = '01.01.2000, 12:34 '; beforeEach(() => { cy.get('@textfield') - .type('01.01.2000 1234') + .type('01.01.2000 1234 ') .should('have.value', beforeMeridiemValue); }); - it('↑ --- 12:34| AM', () => { + it('↑ --- 12:34 |AM', () => { cy.get('@textfield') .type('{upArrow}') - .should('have.value', `${beforeMeridiemValue} AM`) + .should('have.value', `${beforeMeridiemValue}AM`) .should('have.prop', 'selectionStart', beforeMeridiemValue.length) .should('have.prop', 'selectionEnd', beforeMeridiemValue.length); }); - it('↓ --- 12:34| PM', () => { + it('↓ --- 12:34 |PM', () => { cy.get('@textfield') .type('{downArrow}') - .should('have.value', `${beforeMeridiemValue} PM`) + .should('have.value', `${beforeMeridiemValue}PM`) .should('have.prop', 'selectionStart', beforeMeridiemValue.length) .should('have.prop', 'selectionEnd', beforeMeridiemValue.length); }); @@ -306,7 +306,6 @@ describe('DateTime | time modes with meridiem', () => { }); [ - `${beforeTimeValue}12:34`.length, `${beforeTimeValue}12:34 `.length, `${beforeTimeValue}12:34 A`.length, `${beforeTimeValue}12:34 AM`.length, @@ -353,7 +352,6 @@ describe('DateTime | time modes with meridiem', () => { }); [ - `${beforeTimeValue}01:01`.length, `${beforeTimeValue}01:01 `.length, `${beforeTimeValue}01:01 P`.length, `${beforeTimeValue}01:01 PM`.length, @@ -387,8 +385,8 @@ describe('DateTime | time modes with meridiem', () => { }); }); - describe('do nothing for partially completed time string', () => { - it('Empty textfield --- ↑↓ --- Empty textfield', () => { + describe('do nothing when caret is put after any time segment', () => { + it('Empty time part --- ↑↓ --- Empty time part', () => { cy.get('@textfield') .type('01.01.2000 ') .should('have.value', '01.01.2000, ') @@ -398,7 +396,7 @@ describe('DateTime | time modes with meridiem', () => { .should('have.value', '01.01.2000, '); }); - ['1', '12', '12:', '12:3'].forEach((textfieldValue) => { + ['1', '12', '12:', '12:3', '12:34'].forEach((textfieldValue) => { it(`${textfieldValue} --- ↑↓ --- ${textfieldValue}`, () => { cy.get('@textfield') .type(`01.01.2000 ${textfieldValue}`) diff --git a/projects/demo-integrations/src/tests/kit/time/time-meridiem.cy.ts b/projects/demo-integrations/src/tests/kit/time/time-meridiem.cy.ts index 5057832c9..df846b506 100644 --- a/projects/demo-integrations/src/tests/kit/time/time-meridiem.cy.ts +++ b/projects/demo-integrations/src/tests/kit/time/time-meridiem.cy.ts @@ -281,25 +281,25 @@ describe('Time | modes with meridiem', () => { }); describe('toggle meridiem value on ArrowUp / ArrowDown', () => { - describe('Initial value === "12:34|"', () => { + describe('Initial value === "12:34 |"', () => { beforeEach(() => { - cy.get('@textfield').type('1234'); + cy.get('@textfield').type('1234 '); }); - it('↑ --- 12:34| AM', () => { + it('↑ --- 12:34 |AM', () => { cy.get('@textfield') .type('{upArrow}') .should('have.value', '12:34 AM') - .should('have.prop', 'selectionStart', '12:34'.length) - .should('have.prop', 'selectionEnd', '12:34'.length); + .should('have.prop', 'selectionStart', '12:34 '.length) + .should('have.prop', 'selectionEnd', '12:34 '.length); }); - it('↓ --- 12:34| PM', () => { + it('↓ --- 12:34 |PM', () => { cy.get('@textfield') .type('{downArrow}') .should('have.value', '12:34 PM') - .should('have.prop', 'selectionStart', '12:34'.length) - .should('have.prop', 'selectionEnd', '12:34'.length); + .should('have.prop', 'selectionStart', '12:34 '.length) + .should('have.prop', 'selectionEnd', '12:34 '.length); }); }); @@ -314,39 +314,36 @@ describe('Time | modes with meridiem', () => { .type('{moveToStart}'); }); - [ - '12:34'.length, - '12:34 '.length, - '12:34 A'.length, - '12:34 AM'.length, - ].forEach((initialCaretIndex) => { - const initialValueWithCaretLabel = withCaretLabel( - initialValue, - initialCaretIndex, - ); - const toggledValueWithCaretLabel = withCaretLabel( - toggledValue, - initialCaretIndex, - ); - - it(`${initialValueWithCaretLabel} --- ↑ --- ${toggledValueWithCaretLabel}`, () => { - cy.get('@textfield') - .type('{rightArrow}'.repeat(initialCaretIndex)) - .type('{upArrow}') - .should('have.value', toggledValue) - .should('have.prop', 'selectionStart', initialCaretIndex) - .should('have.prop', 'selectionEnd', initialCaretIndex); - }); - - it(`${initialValueWithCaretLabel} --- ↓ --- ${toggledValueWithCaretLabel}`, () => { - cy.get('@textfield') - .type('{rightArrow}'.repeat(initialCaretIndex)) - .type('{downArrow}') - .should('have.value', toggledValue) - .should('have.prop', 'selectionStart', initialCaretIndex) - .should('have.prop', 'selectionEnd', initialCaretIndex); - }); - }); + ['12:34 '.length, '12:34 A'.length, '12:34 AM'.length].forEach( + (initialCaretIndex) => { + const initialValueWithCaretLabel = withCaretLabel( + initialValue, + initialCaretIndex, + ); + const toggledValueWithCaretLabel = withCaretLabel( + toggledValue, + initialCaretIndex, + ); + + it(`${initialValueWithCaretLabel} --- ↑ --- ${toggledValueWithCaretLabel}`, () => { + cy.get('@textfield') + .type('{rightArrow}'.repeat(initialCaretIndex)) + .type('{upArrow}') + .should('have.value', toggledValue) + .should('have.prop', 'selectionStart', initialCaretIndex) + .should('have.prop', 'selectionEnd', initialCaretIndex); + }); + + it(`${initialValueWithCaretLabel} --- ↓ --- ${toggledValueWithCaretLabel}`, () => { + cy.get('@textfield') + .type('{rightArrow}'.repeat(initialCaretIndex)) + .type('{downArrow}') + .should('have.value', toggledValue) + .should('have.prop', 'selectionStart', initialCaretIndex) + .should('have.prop', 'selectionEnd', initialCaretIndex); + }); + }, + ); }); describe('Initial value === "01:01 PM"', () => { @@ -360,42 +357,39 @@ describe('Time | modes with meridiem', () => { .type('{moveToStart}'); }); - [ - '01:01'.length, - '01:01 '.length, - '01:01 P'.length, - '01:01 PM'.length, - ].forEach((initialCaretIndex) => { - const initialValueWithCaretLabel = withCaretLabel( - initialValue, - initialCaretIndex, - ); - const toggledValueWithCaretLabel = withCaretLabel( - toggledValue, - initialCaretIndex, - ); - - it(`${initialValueWithCaretLabel} --- ↑ --- ${toggledValueWithCaretLabel}`, () => { - cy.get('@textfield') - .type('{rightArrow}'.repeat(initialCaretIndex)) - .type('{upArrow}') - .should('have.value', toggledValue) - .should('have.prop', 'selectionStart', initialCaretIndex) - .should('have.prop', 'selectionEnd', initialCaretIndex); - }); - - it(`${initialValueWithCaretLabel} --- ↓ --- ${toggledValueWithCaretLabel}`, () => { - cy.get('@textfield') - .type('{rightArrow}'.repeat(initialCaretIndex)) - .type('{downArrow}') - .should('have.value', toggledValue) - .should('have.prop', 'selectionStart', initialCaretIndex) - .should('have.prop', 'selectionEnd', initialCaretIndex); - }); - }); + ['01:01 '.length, '01:01 P'.length, '01:01 PM'.length].forEach( + (initialCaretIndex) => { + const initialValueWithCaretLabel = withCaretLabel( + initialValue, + initialCaretIndex, + ); + const toggledValueWithCaretLabel = withCaretLabel( + toggledValue, + initialCaretIndex, + ); + + it(`${initialValueWithCaretLabel} --- ↑ --- ${toggledValueWithCaretLabel}`, () => { + cy.get('@textfield') + .type('{rightArrow}'.repeat(initialCaretIndex)) + .type('{upArrow}') + .should('have.value', toggledValue) + .should('have.prop', 'selectionStart', initialCaretIndex) + .should('have.prop', 'selectionEnd', initialCaretIndex); + }); + + it(`${initialValueWithCaretLabel} --- ↓ --- ${toggledValueWithCaretLabel}`, () => { + cy.get('@textfield') + .type('{rightArrow}'.repeat(initialCaretIndex)) + .type('{downArrow}') + .should('have.value', toggledValue) + .should('have.prop', 'selectionStart', initialCaretIndex) + .should('have.prop', 'selectionEnd', initialCaretIndex); + }); + }, + ); }); - describe('do nothing for partially completed time string', () => { + describe('do nothing when caret is put after any time segment', () => { it('Empty textfield --- ↑↓ --- Empty textfield', () => { cy.get('@textfield') .should('have.value', '') @@ -405,7 +399,7 @@ describe('Time | modes with meridiem', () => { .should('have.value', ''); }); - ['1', '12', '12:', '12:3'].forEach((textfieldValue) => { + ['1', '12', '12:', '12:3', '12:34'].forEach((textfieldValue) => { it(`${textfieldValue} --- ↑↓ --- ${textfieldValue}`, () => { cy.get('@textfield') .type(textfieldValue) diff --git a/projects/demo-integrations/src/tests/kit/time/time-step.cy.ts b/projects/demo-integrations/src/tests/kit/time/time-step.cy.ts index e00f65f64..6782e61db 100644 --- a/projects/demo-integrations/src/tests/kit/time/time-step.cy.ts +++ b/projects/demo-integrations/src/tests/kit/time/time-step.cy.ts @@ -1,6 +1,8 @@ import {DemoPath} from '@demo/constants'; import {BROWSER_SUPPORTS_REAL_EVENTS} from 'projects/demo-integrations/src/support/constants'; +import {withCaretLabel} from '../../utils'; + describe('Time', () => { describe('Mode', () => { describe('HH:MM', () => { @@ -117,6 +119,150 @@ describe('Time', () => { }); }); + describe('HH:MM AA', () => { + describe('step = 1', () => { + beforeEach(() => { + cy.visit(`/${DemoPath.Time}/API?mode=HH:MM%20AA&step=1`); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .clear() + .as('textfield'); + }); + + describe('time segment digits stepping', () => { + [ + {value: '12:34 AM', caretIndex: 0, newValue: '00:34 AM'}, + {value: '12:34 AM', caretIndex: '1'.length, newValue: '00:34 AM'}, + { + value: '12:34 AM', + caretIndex: '12'.length, + newValue: '00:34 AM', + }, + { + value: '12:34 AM', + caretIndex: '12:'.length, + newValue: '12:35 AM', + }, + { + value: '12:34 AM', + caretIndex: '12:3'.length, + newValue: '12:35 AM', + }, + { + value: '12:34 AM', + caretIndex: '12:34'.length, + newValue: '12:35 AM', + }, + ].forEach(({value, caretIndex, newValue}) => { + it(`${withCaretLabel(value, caretIndex)} --- ↑ --- ${withCaretLabel(newValue, caretIndex)}`, () => { + cy.get('@textfield') + .type(value) + .type(`{moveToStart}${'{rightArrow}'.repeat(caretIndex)}`) + .type('{upArrow}') + .should('have.value', newValue) + .should('have.a.prop', 'selectionStart', caretIndex) + .should('have.a.prop', 'selectionEnd', caretIndex); + }); + }); + + [ + {value: '12:34 PM', caretIndex: 0, newValue: '11:34 PM'}, + {value: '12:34 PM', caretIndex: '1'.length, newValue: '11:34 PM'}, + { + value: '12:34 PM', + caretIndex: '12'.length, + newValue: '11:34 PM', + }, + { + value: '12:34 PM', + caretIndex: '12:'.length, + newValue: '12:33 PM', + }, + { + value: '12:34 PM', + caretIndex: '12:3'.length, + newValue: '12:33 PM', + }, + { + value: '12:34 PM', + caretIndex: '12:34'.length, + newValue: '12:33 PM', + }, + ].forEach(({value, caretIndex, newValue}) => { + it(`${withCaretLabel(value, caretIndex)} --- ↓ --- ${withCaretLabel(newValue, caretIndex)}`, () => { + cy.get('@textfield') + .type(value) + .type(`{moveToStart}${'{rightArrow}'.repeat(caretIndex)}`) + .type('{downArrow}') + .should('have.value', newValue) + .should('have.a.prop', 'selectionStart', caretIndex) + .should('have.a.prop', 'selectionEnd', caretIndex); + }); + }); + }); + + describe('meridiem switching', () => { + [ + { + value: '12:34 AM', + caretIndex: '12:34 '.length, + newValue: '12:34 PM', + }, + { + value: '12:34 AM', + caretIndex: '12:34 A'.length, + newValue: '12:34 PM', + }, + { + value: '12:34 AM', + caretIndex: '12:34 AM'.length, + newValue: '12:34 PM', + }, + ].forEach(({value, caretIndex, newValue}) => { + it(`${withCaretLabel(value, caretIndex)} --- ↑ --- ${withCaretLabel(newValue, caretIndex)}`, () => { + cy.get('@textfield') + .type(value) + .type(`{moveToStart}${'{rightArrow}'.repeat(caretIndex)}`) + .type('{upArrow}') + .should('have.value', newValue) + .should('have.a.prop', 'selectionStart', caretIndex) + .should('have.a.prop', 'selectionEnd', caretIndex); + }); + }); + + [ + { + value: '12:34 PM', + caretIndex: '12:34 '.length, + newValue: '12:34 AM', + }, + { + value: '12:34 PM', + caretIndex: '12:34 P'.length, + newValue: '12:34 AM', + }, + { + value: '12:34 PM', + caretIndex: '12:34 PM'.length, + newValue: '12:34 AM', + }, + ].forEach(({value, caretIndex, newValue}) => { + it(`${withCaretLabel(value, caretIndex)} --- ↓ --- ${withCaretLabel(newValue, caretIndex)}`, () => { + cy.get('@textfield') + .type(value) + .type(`{moveToStart}${'{rightArrow}'.repeat(caretIndex)}`) + .type('{downArrow}') + .should('have.value', newValue) + .should('have.a.prop', 'selectionStart', caretIndex) + .should('have.a.prop', 'selectionEnd', caretIndex); + }); + }); + }); + }); + }); + describe('HH:MM:SS', () => { describe('step = 1', () => { beforeEach(() => { diff --git a/projects/kit/src/lib/masks/date-time/date-time-mask.ts b/projects/kit/src/lib/masks/date-time/date-time-mask.ts index 6bb36c33e..2a2f8035f 100644 --- a/projects/kit/src/lib/masks/date-time/date-time-mask.ts +++ b/projects/kit/src/lib/masks/date-time/date-time-mask.ts @@ -134,7 +134,7 @@ export function maskitoDateTimeOptionsGenerator({ fullMode, timeSegmentMaxValues: DEFAULT_TIME_SEGMENT_MAX_VALUES, }), - createMeridiemSteppingPlugin(fullMode.indexOf(' AA')), + createMeridiemSteppingPlugin(fullMode.indexOf('AA')), ], }; } diff --git a/projects/kit/src/lib/masks/time/time-mask.ts b/projects/kit/src/lib/masks/time/time-mask.ts index 6c1e53ed0..eb3c456c5 100644 --- a/projects/kit/src/lib/masks/time/time-mask.ts +++ b/projects/kit/src/lib/masks/time/time-mask.ts @@ -65,7 +65,7 @@ export function maskitoTimeOptionsGenerator({ step, timeSegmentMaxValues: enrichedTimeSegmentMaxValues, }), - createMeridiemSteppingPlugin(mode.indexOf(' AA')), + createMeridiemSteppingPlugin(mode.indexOf('AA')), ], overwriteMode: 'replace', };