import { Component, NgZone } from '@angular/core';
/* tslint:disable:max-classes-per-file max-file-line-count component-class-suffix */
/**
* @copyright Angular ng-bootstrap team
*/
import { discardPeriodicTasks, fakeAsync, inject, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { CarouselComponent, CarouselConfig, CarouselModule } from '../../carousel/index';
import { createGenericTestComponent } from './test/common';
@Component({selector: 'test-cmp', template: ''})
class TestComponent {
activeSlideIndex: number;
keyboard: boolean;
}
const createTestComponent = (html: string) =>
createGenericTestComponent(html, TestComponent);
function expectActiveSlides(nativeEl: HTMLDivElement, active: boolean[]): void {
const slideElms = nativeEl.querySelectorAll('.carousel-item');
const indicatorElms = nativeEl.querySelectorAll(
'ol.carousel-indicators > li'
);
expect(slideElms.length).toBe(active.length);
expect(indicatorElms.length).toBe(active.length);
for (let i = 0; i < active.length; i++) {
if (active[i]) {
expect(slideElms[i]).toHaveCssClass('active');
expect(indicatorElms[i]).toHaveCssClass('active');
} else {
expect(slideElms[i]).not.toHaveCssClass('active');
expect(indicatorElms[i]).not.toHaveCssClass('active');
}
}
}
describe('ngb-carousel', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestComponent],
imports: [CarouselModule.forRoot()]
});
});
it('should initialize inputs with default values', () => {
const defaultConfig = new CarouselConfig();
const carousel = new CarouselComponent(
new CarouselConfig(),
new NgZone({})
);
expect(carousel.interval).toBe(defaultConfig.interval);
expect(carousel.noWrap).toBe(defaultConfig.noWrap);
expect(carousel.showIndicators).toBe(defaultConfig.showIndicators);
// expect(carousel.keyboard).toBe(defaultConfig.keyboard);
});
it(
'should render slides and navigation indicators',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
const slideElms = fixture.nativeElement.querySelectorAll(
'.carousel-item'
);
expect(slideElms.length).toBe(2);
expect(slideElms[0].textContent).toMatch(/slide1/);
expect(slideElms[1].textContent).toMatch(/slide2/);
expect(
fixture.nativeElement.querySelectorAll('ol.carousel-indicators > li')
.length
).toBe(2);
discardPeriodicTasks();
})
);
it(
'should mark the first slide as active by default',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
expectActiveSlides(fixture.nativeElement, [true, false]);
discardPeriodicTasks();
})
);
it(
'should mark the requested slide as active',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
fixture.componentInstance.activeSlideIndex = 1;
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true]);
discardPeriodicTasks();
})
);
it(
'should auto-correct when slide index is undefined',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
expectActiveSlides(fixture.nativeElement, [true, false]);
discardPeriodicTasks();
})
);
it(
'should change slide on indicator click',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
const indicatorElms = fixture.nativeElement.querySelectorAll(
'ol.carousel-indicators > li'
);
expectActiveSlides(fixture.nativeElement, [true, false]);
indicatorElms[1].click();
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true]);
discardPeriodicTasks();
})
);
it(
'should change slide on carousel control click',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
const prevControlElm = fixture.nativeElement.querySelector(
'.carousel-control-prev'
);
const nextControlElm = fixture.nativeElement.querySelector(
'.carousel-control-next'
);
expectActiveSlides(fixture.nativeElement, [true, false]);
nextControlElm.click(); // next
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true]);
prevControlElm.click(); // prev
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [true, false]);
discardPeriodicTasks();
})
);
it(
'should change slide on time passage (default interval value)',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
expectActiveSlides(fixture.nativeElement, [true, false]);
tick(6000);
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true]);
discardPeriodicTasks();
})
);
it(
'should change slide on time passage (custom interval value)',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
expectActiveSlides(fixture.nativeElement, [true, false]);
tick(1000);
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [true, false]);
tick(1200);
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true]);
discardPeriodicTasks();
})
);
it(
'should not change slide on time passage (custom interval value is zero)',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
expectActiveSlides(fixture.nativeElement, [true, false]);
tick(1000);
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [true, false]);
tick(1200);
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [true, false]);
discardPeriodicTasks();
})
);
it(
'should pause / resume slide change with time passage on mouse enter / leave',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
const carouselDebugEl = fixture.debugElement.query(
By.directive(CarouselComponent)
);
expectActiveSlides(fixture.nativeElement, [true, false]);
carouselDebugEl.children[0].triggerEventHandler('mouseenter', {});
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [true, false]);
tick(6000);
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [true, false]);
carouselDebugEl.children[0].triggerEventHandler('mouseleave', {});
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [true, false]);
tick(6000);
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true]);
discardPeriodicTasks();
})
);
it(
'should wrap slide changes by default',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
const prevControlElm = fixture.nativeElement.querySelector(
'.carousel-control-prev'
);
const nextControlElm = fixture.nativeElement.querySelector(
'.carousel-control-next'
);
expectActiveSlides(fixture.nativeElement, [true, false]);
nextControlElm.click(); // next
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true]);
nextControlElm.click(); // next
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [true, false]);
prevControlElm.click(); // prev
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true]);
discardPeriodicTasks();
})
);
it(
'should not wrap slide changes by when requested',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
const prevControlElm = fixture.nativeElement.querySelector(
'.carousel-control-prev'
);
const nextControlElm = fixture.nativeElement.querySelector(
'.carousel-control-next'
);
expectActiveSlides(fixture.nativeElement, [true, false]);
prevControlElm.click(); // prev
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [true, false]);
nextControlElm.click(); // next
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true]);
nextControlElm.click(); // next
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true]);
discardPeriodicTasks();
})
);
xit(
'should change on key arrowRight and arrowLeft',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
expectActiveSlides(fixture.nativeElement, [true, false]);
fixture.debugElement
.query(By.directive(CarouselComponent))
.triggerEventHandler('keydown.arrowRight', {}); // next()
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true]);
fixture.debugElement
.query(By.directive(CarouselComponent))
.triggerEventHandler('keydown.arrowLeft', {}); // prev()
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [true, false]);
fixture.componentInstance.keyboard = false;
fixture.detectChanges();
fixture.debugElement
.query(By.directive(CarouselComponent))
.triggerEventHandler('keydown.arrowRight', {}); // prev()
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [true, false]);
discardPeriodicTasks();
})
);
xit(
'should listen to keyevents based on keyboard attribute',
fakeAsync(() => {
const html = `
slide1
slide2
`;
const fixture = createTestComponent(html);
expectActiveSlides(fixture.nativeElement, [true, false]);
fixture.componentInstance.keyboard = false;
fixture.detectChanges();
fixture.debugElement
.query(By.directive(CarouselComponent))
.triggerEventHandler('keydown.arrowRight', {}); // prev()
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [true, false]);
fixture.componentInstance.keyboard = true;
fixture.detectChanges();
fixture.debugElement
.query(By.directive(CarouselComponent))
.triggerEventHandler('keydown.arrowRight', {}); // next()
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true]);
discardPeriodicTasks();
})
);
describe('Custom config', () => {
let config: CarouselConfig;
beforeEach(() => {
TestBed.configureTestingModule({imports: [CarouselModule.forRoot()]});
});
beforeEach(
inject([CarouselConfig], (c: CarouselConfig) => {
config = c;
config.interval = 1000;
config.noWrap = true;
config.showIndicators = true;
// config.keyboard = false;
})
);
it('should initialize inputs with provided config', () => {
const fixture = TestBed.createComponent(CarouselComponent);
fixture.detectChanges();
const carousel = fixture.componentInstance;
expect(carousel.interval).toBe(config.interval);
expect(carousel.noWrap).toBe(config.noWrap);
expect(carousel.showIndicators).toBe(config.showIndicators);
// expect(carousel.keyboard).toBe(config.keyboard);
});
});
describe('Custom config as provider', () => {
const config = new CarouselConfig();
config.interval = 1000;
config.noWrap = true;
config.showIndicators = true;
// config.keyboard = false;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CarouselModule.forRoot()],
providers: [{provide: CarouselConfig, useValue: config}]
});
});
it('should initialize inputs with provided config as provider', () => {
const fixture = TestBed.createComponent(CarouselComponent);
fixture.detectChanges();
const carousel = fixture.componentInstance;
expect(carousel.interval).toBe(config.interval);
expect(carousel.noWrap).toBe(config.noWrap);
expect(carousel.showIndicators).toBe(config.showIndicators);
// expect(carousel.keyboard).toBe(config.keyboard);
});
});
});