Skip to content

Commit

Permalink
test(carousel): feat test carousel (#676)
Browse files Browse the repository at this point in the history
* temp carousel spec, part1

* tests(carousel component), fix ts issue in accordeon spec

* chore(ci): use node 4

* test(carousel): added tests

* update tests to work with rc4, merge dev

* fix node version in travis
  • Loading branch information
otelnov authored and valorkin committed Jul 19, 2016
1 parent 06abe84 commit 9466899
Show file tree
Hide file tree
Showing 2 changed files with 216 additions and 0 deletions.
209 changes: 209 additions & 0 deletions components/carousel/carousel.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
import {Component} from '@angular/core';
import {
it,
expect,
inject,
fakeAsync,
beforeEach,
discardPeriodicTasks
} from '@angular/core/testing';
import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing';
import {NgModel} from '@angular/common';
import {CAROUSEL_DIRECTIVES} from '../carousel';

const html = `
<div id="c1">
<carousel [interval]="myInterval" [noWrap]="noWrapSlides">
<slide *ngFor="let slide of slides; let index=index"
[active]="slide.active">
<img [src]="slide.image" style="margin:auto;">
<div class="carousel-caption">
<h4>Slide {{index}}</h4>
<p>{{slide.text}}</p>
</div>
</slide>
</carousel>
</div>
<div id="c2">
<carousel>
<slide>slide1</slide>
<slide>slide2</slide>
</carousel>
</div>
`;

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].classList).toContain('active');
expect(indicatorElms[i].classList).toContain('active');
} else {
expect(slideElms[i].classList).not.toContain('active');
expect(indicatorElms[i].classList).not.toContain('active');
}
}
}

describe('Component: Carousel', () => {
let fixture:ComponentFixture<any>;
let context:any;
let element:any;
let clean:any;

beforeEach(fakeAsync(inject([TestComponentBuilder], (tcb:TestComponentBuilder) => {
return tcb
.overrideTemplate(TestCarouselComponent, html)
.createAsync(TestCarouselComponent)
.then((f:ComponentFixture<any>) => {
fixture = f;
context = fixture.componentInstance;
fixture.detectChanges();
element = fixture.nativeElement.querySelector('#c1');
clean = fixture.nativeElement.querySelector('#c2');
discardPeriodicTasks();
});
})));

it('should set first slide as active by default', () => {
expectActiveSlides(element, [true, false, false]);
});

// TODO:
xit('should be able to select a slide via model changes', () => {
context.slides[2].active = true;
fixture.detectChanges();
expectActiveSlides(element, [false, false, true]);
});

it('should create next/prev nav button', () => {
let prev = element.querySelectorAll('a.left');
let next = element.querySelectorAll('a.right');
expect(prev.length).toBe(1);
expect(next.length).toBe(1);
});

it('should display slide indicators', () => {
let indicators = element.querySelectorAll('ol.carousel-indicators > li');
expect(indicators.length).toBe(3);
});

// TODO:
xit('should hide navigation when only one slide', () => {
context.slides.splice(0, 2);
fixture.detectChanges();
expect(context.slides.length).toBe(1);
let indicators = element.querySelectorAll('ol.carousel-indicators > li');
expect(indicators.length).toBe(0);
let prev = element.querySelectorAll('a.left');
expect(prev.length).toBe(0);
let next = element.querySelectorAll('a.right');
expect(next.length).toBe(0);
});

// TODO:
xit('should disable prev button when slide index is 0 and noWrap is truthy', () => {
context.noWrapSlides = true;
fixture.detectChanges();
let prev = element.querySelector('a.left');
expect(prev).toHaveCssClass('disabled');
});

// TODO:
xit('should disable next button when last slide is active and noWrap is truthy', () => {
context.noWrapSlides = true;
context.slides[2].active = true;
fixture.detectChanges();
let next = element.querySelector('a.right');
expect(next).toHaveCssClass('disabled');
});

it('should change slide on indicator click', () => {
let indicators = element.querySelectorAll('ol.carousel-indicators > li');
expectActiveSlides(element, [true, false, false]);
indicators[2].click();
fixture.detectChanges();
expectActiveSlides(element, [false, false, true]);
indicators[1].click();
fixture.detectChanges();
expectActiveSlides(element, [false, true, false]);
});

it('should change slide on carousel control click', () => {
const prev = element.querySelector('a.left');
const next = element.querySelector('a.right');
next.click();
fixture.detectChanges();
expectActiveSlides(element, [false, true, false]);
prev.click();
fixture.detectChanges();
expectActiveSlides(element, [true, false, false]);
});

// it('should change slide on time passage (default)', fakeAsync(() => {
// expectActiveSlides(clean, [true, false]);
// tick(6000);
// fixture.detectChanges();
// expectActiveSlides(clean, [false, true]);
// }));

it('should wrap slide changes by default', () => {
const prev = element.querySelector('a.left');
const next = element.querySelector('a.right');
expectActiveSlides(element, [true, false, false]);
next.click();
fixture.detectChanges();
expectActiveSlides(element, [false, true, false]);
next.click();
fixture.detectChanges();
expectActiveSlides(element, [false, false, true]);
next.click();
fixture.detectChanges();
expectActiveSlides(element, [true, false, false]);
prev.click();
fixture.detectChanges();
expectActiveSlides(element, [false, false, true]);
});

it('should not wrap slide changes if noWrap == true', () => {
context.noWrapSlides = true;
fixture.detectChanges();
const prev = element.querySelector('a.left');
const next = element.querySelector('a.right');
expectActiveSlides(element, [true, false, false]);
prev.click();
fixture.detectChanges();
expectActiveSlides(element, [true, false, false]);
next.click();
fixture.detectChanges();
expectActiveSlides(element, [false, true, false]);
next.click();
fixture.detectChanges();
expectActiveSlides(element, [false, false, true]);
next.click();
fixture.detectChanges();
expectActiveSlides(element, [false, false, true]);
});
});

@Component({
selector: 'carousel-test',
directives: [CAROUSEL_DIRECTIVES, NgModel],
template: ''
})

class TestCarouselComponent {
public myInterval:number = 5000;
public noWrapSlides:boolean = false;
public slides:Array<any> = [
{image: '//placekitten.com/600/300', text: 'slide0'},
{image: '//placekitten.com/600/300', text: 'slide1'},
{image: '//placekitten.com/600/300', text: 'slide2'}
];
}
7 changes: 7 additions & 0 deletions components/carousel/carousel.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ const NAVIGATION:any = {

// todo:
// (ng-swipe-right)="prev()" (ng-swipe-left)="next()"
/**
* Problems:
* 1) if we set an active slide via model changes, .active class remains on a current slide.
* 2) if we have only one slide, we shouldn't show prev/next nav buttons
* 3) if first or last slide is active and noWrap is true, there should be "disabled" class on the nav buttons.
* 4) default interval should be equal 5000
*/
@Component({
selector: 'carousel',
directives: [NgFor],
Expand Down

0 comments on commit 9466899

Please sign in to comment.