Skip to content

Commit c2c1b8b

Browse files
authored
test(*): increase coverage for multiple components (#17104)
1 parent 864c522 commit c2c1b8b

File tree

10 files changed

+952
-3
lines changed

10 files changed

+952
-3
lines changed

projects/igniteui-angular/calendar/src/calendar/month-picker/month-picker.component.spec.ts

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,183 @@ describe('IgxMonthPicker', () => {
552552
currentValue: new Date(2019, 1, 1)
553553
});
554554
});
555+
556+
it('should return the correct next and previous years via getNextYear/getPreviousYear', () => {
557+
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);
558+
fixture.detectChanges();
559+
const monthPicker = fixture.componentInstance.monthPicker;
560+
// viewDate is 2019
561+
expect(monthPicker.getNextYear()).toBe(2020);
562+
expect(monthPicker.getPreviousYear()).toBe(2018);
563+
});
564+
565+
it('should navigate forward one year via PageDown in default (year) view', () => {
566+
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);
567+
fixture.detectChanges();
568+
const monthPicker = fixture.componentInstance.monthPicker;
569+
const wrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper'));
570+
wrapper.nativeElement.focus();
571+
fixture.detectChanges();
572+
573+
const initialYear = monthPicker.viewDate.getFullYear();
574+
UIInteractions.triggerKeyDownEvtUponElem('PageDown', document.activeElement);
575+
fixture.detectChanges();
576+
577+
expect(monthPicker.viewDate.getFullYear()).toBe(initialYear + 1);
578+
});
579+
580+
it('should navigate backward one year via PageUp in default (year) view', () => {
581+
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);
582+
fixture.detectChanges();
583+
const monthPicker = fixture.componentInstance.monthPicker;
584+
const wrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper'));
585+
wrapper.nativeElement.focus();
586+
fixture.detectChanges();
587+
588+
const initialYear = monthPicker.viewDate.getFullYear();
589+
UIInteractions.triggerKeyDownEvtUponElem('PageUp', document.activeElement);
590+
fixture.detectChanges();
591+
592+
expect(monthPicker.viewDate.getFullYear()).toBe(initialYear - 1);
593+
});
594+
595+
it('should navigate forward one year via PageDown in default (year) view', () => {
596+
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);
597+
fixture.detectChanges();
598+
const monthPicker = fixture.componentInstance.monthPicker;
599+
const wrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper'));
600+
wrapper.nativeElement.focus();
601+
fixture.detectChanges();
602+
603+
const initialYear = monthPicker.viewDate.getFullYear();
604+
UIInteractions.triggerKeyDownEvtUponElem('PageDown', document.activeElement);
605+
fixture.detectChanges();
606+
607+
expect(monthPicker.viewDate.getFullYear()).toBe(initialYear + 1);
608+
});
609+
610+
it('should navigate backward one page via PageUp in decade (years) view', () => {
611+
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);
612+
fixture.detectChanges();
613+
const monthPicker = fixture.componentInstance.monthPicker;
614+
// Switch to decade view
615+
monthPicker.activeView = IgxCalendarView.Decade;
616+
fixture.detectChanges();
617+
618+
const wrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper'));
619+
wrapper.nativeElement.focus();
620+
fixture.detectChanges();
621+
622+
const initialYear = monthPicker.viewDate.getFullYear();
623+
UIInteractions.triggerKeyDownEvtUponElem('PageUp', document.activeElement);
624+
fixture.detectChanges();
625+
626+
// In decade view, PageUp calls previousPage which moves back 15 years
627+
expect(monthPicker.viewDate.getFullYear()).toBe(initialYear - 15);
628+
});
629+
630+
it('should navigate forward one page via PageDown in decade (years) view', () => {
631+
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);
632+
fixture.detectChanges();
633+
const monthPicker = fixture.componentInstance.monthPicker;
634+
monthPicker.activeView = IgxCalendarView.Decade;
635+
fixture.detectChanges();
636+
637+
const wrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper'));
638+
wrapper.nativeElement.focus();
639+
fixture.detectChanges();
640+
641+
const initialYear = monthPicker.viewDate.getFullYear();
642+
UIInteractions.triggerKeyDownEvtUponElem('PageDown', document.activeElement);
643+
fixture.detectChanges();
644+
645+
// In decade view, PageDown calls nextPage which moves forward 15 years
646+
expect(monthPicker.viewDate.getFullYear()).toBe(initialYear + 15);
647+
});
648+
649+
it('should navigate to January via Home key in default (year) view', () => {
650+
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);
651+
fixture.detectChanges();
652+
const wrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper'));
653+
wrapper.nativeElement.focus();
654+
fixture.detectChanges();
655+
656+
UIInteractions.triggerKeyDownEvtUponElem('Home', document.activeElement);
657+
fixture.detectChanges();
658+
659+
const dom = fixture.debugElement;
660+
const selected = dom.query(By.css('.igx-calendar-view__item--selected'));
661+
expect(selected.nativeElement.textContent.trim()).toMatch('Jan');
662+
});
663+
664+
it('should navigate to December via End key in default (year) view', () => {
665+
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);
666+
fixture.detectChanges();
667+
const wrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper'));
668+
wrapper.nativeElement.focus();
669+
fixture.detectChanges();
670+
671+
UIInteractions.triggerKeyDownEvtUponElem('End', document.activeElement);
672+
fixture.detectChanges();
673+
674+
const dom = fixture.debugElement;
675+
const selected = dom.query(By.css('.igx-calendar-view__item--selected'));
676+
expect(selected.nativeElement.textContent.trim()).toMatch('Dec');
677+
});
678+
679+
it('should navigate to first year in view via Home key in decade (years) view', () => {
680+
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);
681+
fixture.detectChanges();
682+
const monthPicker = fixture.componentInstance.monthPicker;
683+
monthPicker.activeView = IgxCalendarView.Decade;
684+
fixture.detectChanges();
685+
686+
const wrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper'));
687+
wrapper.nativeElement.focus();
688+
fixture.detectChanges();
689+
690+
UIInteractions.triggerKeyDownEvtUponElem('Home', document.activeElement);
691+
fixture.detectChanges();
692+
693+
const dom = fixture.debugElement;
694+
const years = dom.queryAll(By.css('.igx-calendar-view__item'));
695+
const selected = dom.query(By.css('.igx-calendar-view__item--selected'));
696+
expect(selected.nativeElement).toBe(years[0].nativeElement);
697+
});
698+
699+
it('should navigate to last year in view via End key in decade (years) view', () => {
700+
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);
701+
fixture.detectChanges();
702+
const monthPicker = fixture.componentInstance.monthPicker;
703+
monthPicker.activeView = IgxCalendarView.Decade;
704+
fixture.detectChanges();
705+
706+
const wrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper'));
707+
wrapper.nativeElement.focus();
708+
fixture.detectChanges();
709+
710+
UIInteractions.triggerKeyDownEvtUponElem('End', document.activeElement);
711+
fixture.detectChanges();
712+
713+
const dom = fixture.debugElement;
714+
const years = dom.queryAll(By.css('.igx-calendar-view__item'));
715+
const selected = dom.query(By.css('.igx-calendar-view__item--selected'));
716+
expect(selected.nativeElement).toBe(years[years.length - 1].nativeElement);
717+
});
718+
719+
it('should change the active view to decade via activeViewDecade and focus the years view', () => {
720+
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);
721+
fixture.detectChanges();
722+
const monthPicker = fixture.componentInstance.monthPicker;
723+
724+
expect(monthPicker.activeView).toBe(IgxCalendarView.Year);
725+
726+
const yearBtn = fixture.debugElement.query(By.css('.igx-calendar-picker__date'));
727+
UIInteractions.simulateMouseDownEvent(yearBtn.nativeElement);
728+
fixture.detectChanges();
729+
730+
expect(monthPicker.activeView).toBe(IgxCalendarView.Decade);
731+
});
555732
});
556733

557734
@Component({

projects/igniteui-angular/directives/src/directives/drag-drop/drag-drop.spec.ts

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,6 +1924,140 @@ describe('Nested igxDrag elements', () => {
19241924
});
19251925
})
19261926

1927+
describe('igxDrag touch, mouse, pointerLost and shadow root coverage', () => {
1928+
let fix: ComponentFixture<TestDragDropComponent>;
1929+
let dragDirsRects: { top: number; left: number; right: number; bottom: number }[];
1930+
1931+
beforeEach(waitForAsync(() => {
1932+
TestBed.configureTestingModule({
1933+
imports: [TestDragDropComponent]
1934+
}).compileComponents();
1935+
}));
1936+
1937+
beforeEach(() => {
1938+
fix = TestBed.createComponent(TestDragDropComponent);
1939+
fix.detectChanges();
1940+
dragDirsRects = getDragDirsRects(fix.componentInstance.dragElems);
1941+
});
1942+
1943+
it('should handle touchstart event to initiate drag when touch events are used', async () => {
1944+
const firstDrag = fix.componentInstance.dragElems.first;
1945+
const firstElement = firstDrag.element.nativeElement;
1946+
const startingX = (dragDirsRects[0].left + dragDirsRects[0].right) / 2;
1947+
const startingY = (dragDirsRects[0].top + dragDirsRects[0].bottom) / 2;
1948+
1949+
spyOn(firstDrag.dragStart, 'emit');
1950+
1951+
// In Chrome headless, pointerEventsEnabled is true (PointerEvent is defined).
1952+
// Mock the properties so the touch path is taken in ngAfterContentInit
1953+
spyOnProperty(firstDrag, 'pointerEventsEnabled').and.returnValue(false);
1954+
spyOnProperty(firstDrag, 'touchEventsEnabled').and.returnValue(true);
1955+
1956+
// Re-bind events with the mocked touch path
1957+
firstDrag.ngAfterContentInit();
1958+
1959+
// Simulate touchstart — triggers onPointerDown via touchstart path
1960+
UIInteractions.simulateTouchStartEvent(firstElement, startingX, startingY);
1961+
fix.detectChanges();
1962+
await wait();
1963+
1964+
// Simulate touch move via document.defaultView (bound by ngAfterContentInit touch path)
1965+
UIInteractions.simulateTouchMoveEvent(document.defaultView, startingX + 20, startingY + 20);
1966+
fix.detectChanges();
1967+
await wait(100);
1968+
1969+
// After a 20px move the drag should have started
1970+
expect(firstDrag.dragStart.emit).toHaveBeenCalled();
1971+
1972+
UIInteractions.simulateTouchEndEvent(document.defaultView, startingX + 20, startingY + 20);
1973+
fix.detectChanges();
1974+
await wait();
1975+
});
1976+
1977+
it('should handle mousedown event to initiate drag when mouse events are used', async () => {
1978+
const firstDrag = fix.componentInstance.dragElems.first;
1979+
const firstElement = firstDrag.element.nativeElement;
1980+
const startingX = (dragDirsRects[0].left + dragDirsRects[0].right) / 2;
1981+
const startingY = (dragDirsRects[0].top + dragDirsRects[0].bottom) / 2;
1982+
1983+
spyOn(firstDrag.dragStart, 'emit');
1984+
// Spy on pointerEventsEnabled to return false so the mousedown path is taken
1985+
spyOnProperty(firstDrag, 'pointerEventsEnabled').and.returnValue(false);
1986+
spyOnProperty(firstDrag, 'touchEventsEnabled').and.returnValue(false);
1987+
1988+
// Re-init the event subscriptions with the mocked properties
1989+
firstDrag.ngAfterContentInit();
1990+
1991+
UIInteractions.simulateMouseEvent('mousedown', firstElement, startingX, startingY);
1992+
fix.detectChanges();
1993+
await wait();
1994+
1995+
UIInteractions.simulateMouseEvent('mousemove', document.body, startingX + 20, startingY + 20);
1996+
fix.detectChanges();
1997+
await wait(100);
1998+
1999+
expect(firstDrag.dragStart.emit).toHaveBeenCalled();
2000+
2001+
UIInteractions.simulateMouseEvent('mouseup', document.body, startingX + 20, startingY + 20);
2002+
fix.detectChanges();
2003+
await wait();
2004+
});
2005+
2006+
it('should call onPointerLost early return when _clicked is false', async () => {
2007+
const firstDrag = fix.componentInstance.dragElems.first;
2008+
2009+
spyOn(firstDrag.dragEnd, 'emit');
2010+
2011+
// _clicked starts as false — calling onPointerLost should return immediately
2012+
firstDrag.onPointerLost({ pageX: 100, pageY: 100 });
2013+
2014+
expect(firstDrag.dragEnd.emit).not.toHaveBeenCalled();
2015+
});
2016+
2017+
it('should emit dragEnd on onPointerLost when drag was in progress', async () => {
2018+
const firstDrag = fix.componentInstance.dragElems.first;
2019+
const firstElement = firstDrag.element.nativeElement;
2020+
const startingX = (dragDirsRects[0].left + dragDirsRects[0].right) / 2;
2021+
const startingY = (dragDirsRects[0].top + dragDirsRects[0].bottom) / 2;
2022+
2023+
spyOn(firstDrag.dragEnd, 'emit');
2024+
2025+
UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY);
2026+
fix.detectChanges();
2027+
await wait();
2028+
2029+
UIInteractions.simulatePointerEvent('pointermove', firstElement, startingX + 10, startingY + 10);
2030+
fix.detectChanges();
2031+
await wait(100);
2032+
2033+
// Ghost is now active — onPointerLost should emit dragEnd
2034+
UIInteractions.simulatePointerEvent('lostpointercapture', firstDrag.ghostElement, startingX + 10, startingY + 10);
2035+
fix.detectChanges();
2036+
await wait();
2037+
2038+
expect(firstDrag.dragEnd.emit).toHaveBeenCalled();
2039+
});
2040+
2041+
it('should return elements from shadow root via getFromShadowRoot', () => {
2042+
const firstDrag = fix.componentInstance.dragElems.first;
2043+
2044+
// Create a mock element with a shadowRoot that returns elements from point
2045+
const innerElem = document.createElement('span');
2046+
const shadowHost = document.createElement('div');
2047+
const shadowRoot = shadowHost.attachShadow({ mode: 'open' });
2048+
shadowRoot.appendChild(innerElem);
2049+
2050+
const mockParentElems = [shadowHost];
2051+
2052+
// Mock elementsFromPoint to return our inner element
2053+
spyOn(shadowRoot, 'elementsFromPoint').and.returnValue([innerElem]);
2054+
2055+
const result = (firstDrag as any).getFromShadowRoot(shadowHost, 100, 100, mockParentElems);
2056+
2057+
expect(result).toContain(innerElem);
2058+
});
2059+
})
2060+
19272061
const getDragDirsRects = (dragDirs: QueryList<IgxDragDirective>) => {
19282062
const dragDirsRects = [];
19292063
dragDirs.forEach((dragDir) => {

projects/igniteui-angular/directives/src/directives/mask/mask.directive.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,40 @@ describe('igxMask', () => {
584584
expect(inputElement.nativeElement.selectionEnd).toEqual(8);
585585
expect(inputHTMLElement.value).toEqual('(123) __67-890');
586586
});
587+
588+
it('should handle deleteContentBackward input event after compositionend (line 209 branch)', fakeAsync(() => {
589+
// This test covers the branch at line 209 of mask.directive.ts:
590+
// After compositionend, Chromium fires an input event with inputType='deleteContentBackward'.
591+
// The branch adjusts start/end indexes to account for mask literals.
592+
const fixture = TestBed.createComponent(MaskComponent);
593+
fixture.detectChanges();
594+
tick();
595+
596+
const inputDebugEl = fixture.debugElement.query(By.css('input'));
597+
const inputEl = inputDebugEl.nativeElement as HTMLInputElement;
598+
599+
// Focus and set a starting selection
600+
inputDebugEl.triggerEventHandler('focus', {});
601+
fixture.detectChanges();
602+
603+
// Use compositionstart → compositionend to set up _compositionStartIndex and _compositionValue
604+
UIInteractions.simulateCompositionEvent('123', inputDebugEl, 0, 3, false);
605+
fixture.detectChanges();
606+
tick();
607+
608+
// Now trigger an InputEvent with inputType='deleteContentBackward' and _key != BACKSPACE
609+
// This is the path Chromium takes after compositionend
610+
const deleteEvent = new InputEvent('input', {
611+
bubbles: true,
612+
inputType: 'deleteContentBackward'
613+
});
614+
inputEl.dispatchEvent(deleteEvent);
615+
fixture.detectChanges();
616+
tick();
617+
618+
// The branch should have run without throwing; mask is still applied
619+
expect(inputEl.value).toBeDefined();
620+
}));
587621
});
588622

589623
describe('igxMaskDirective ControlValueAccessor Unit', () => {

0 commit comments

Comments
 (0)