package org.sikuli.slides.api.slideshow;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.sikuli.slides.api.Context;
import org.sikuli.slides.api.actions.ActionExecutionException;
import org.sikuli.slides.api.models.Slide;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.*;
public class DefaultSlideShowControllerTest {
List<Slide> slides;
DefaultSlideShowController slideshow;
private Slide slide1;
private Slide slide2;
private Slide slide3;
private Context context;
void pause(long msecs){
try {
Thread.sleep(msecs);
} catch (InterruptedException e) {
}
}
static public class TestSlide extends Slide {
private long duration;
private int number;
private boolean throwException = false;
public TestSlide(long waitDuration, int number) {
this.duration = waitDuration;
this.number = number;
}
public void setThrowException(boolean throwException){
this.throwException = throwException;
}
/**
* Execute and wait for execution to finish
*/
public void execute(Context context) throws ActionExecutionException{
synchronized (this){
try {
this.wait(duration);
} catch (InterruptedException e) {
}
}
if (throwException){
throw new ActionExecutionException("exception", this);
}
}
public void stop(){
synchronized(this){
this.notify();
}
}
public long getDuration() {
return duration;
}
public String toString(){
return Objects.toStringHelper(getClass()).add("number", number).toString();
}
}
@Before
public void setUp(){
context = new Context();
slide1 = spy(new TestSlide(500,1));
slide2 = spy(new TestSlide(500,2));
slide3 = spy(new TestSlide(500,3));
slides = Lists.newArrayList(slide1, slide2, slide3);
slideshow = new DefaultSlideShowController(context, slides);
}
@Test
public void testStartExecuteAllThreeSlides() throws ActionExecutionException {
slideshow.start();
pause(1600);
verify(slide1).execute(any(Context.class));
verify(slide2).execute(any(Context.class));
verify(slide3).execute(any(Context.class));
}
@Test
public void testAfterSlide3_JumpToSlide1AndPlay() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(1600);
slideshow.jumpTo(0);
slideshow.play();
}
}.start();
pause(2000);
verify(slide1, times(2)).execute(any(Context.class));
verify(slide2).execute(any(Context.class));
verify(slide3).execute(any(Context.class));
}
@Test
public void testAfterSlide3_JumpToSlide1() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(1600);
slideshow.jumpTo(0);
}
}.start();
pause(2000);
verify(slide1).execute(any(Context.class));
verify(slide2).execute(any(Context.class));
verify(slide3).execute(any(Context.class));
}
@Test
public void testDuringSlide2_Pause() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(600);
slideshow.pause();
}
}.start();
pause(1000);
verify(slide1).execute(any(Context.class));
verify(slide2).execute(any(Context.class));
verify(slide2).stop();
verify(slide3,never()).execute(any(Context.class));
}
@Test
public void testDuringSlide1_Quit() throws ActionExecutionException, InterruptedException {
slideshow.start();
new Thread(){
public void run(){
pause(100);
slideshow.quit();
}
}.start();
pause(150);
// should cause slide1 to stop
verify(slide1).stop();
// should never execute slide 2
verify(slide2, never()).execute(any(Context.class));
// should never execute slide 3
verify(slide3, never()).execute(any(Context.class));
}
@Test
public void testDuringSlide1_Next() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(100);
slideshow.next();
}
}.start();
pause(200);
verify(slide1).stop();
verify(slide2).execute(any(Context.class));
verify(slide3, never()).execute(any(Context.class));
}
@Test
public void testDuringSlide1_NextNext() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(100);
slideshow.next();
pause(100);
slideshow.next();
}
}.start();
pause(500);
// should stop slide1
verify(slide1).stop();
// should execute slide 3
verify(slide3).execute(any(Context.class));
}
@Test
public void testDuringSlide1_Previous() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(100);
slideshow.previous();
}
}.start();
pause(150);
// should not cause slide1 to stop
verify(slide1,never()).stop();
// should not start executing slide2
verify(slide2,never()).execute(any(Context.class));
}
@Test
public void testDuringSlide1_NextNextNext() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(100);
slideshow.next();
pause(100);
slideshow.next();
pause(100);
slideshow.next();
}
}.start();
pause(500);
verify(slide1).stop();
verify(slide3).execute(any(Context.class));
}
@Test
public void testDuringSlide2_Previous() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(600);
slideshow.previous();
}
}.start();
pause(800);
verify(slide2).execute(any(Context.class));
verify(slide2).stop();
// should go back to execute slide 1
verify(slide1, times(2)).execute(any(Context.class));
// should not have already executed slide 3
verify(slide3, never()).execute(any(Context.class));
// pause(1500);
// // should continue to execute slide 2
// verify(slide2, times(2)).execute(any(Context.class));
// verify(slide3).execute(any(Context.class));
//
}
@Test
public void testDuringSlide1_JumpToSlide3() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(100);
slideshow.jumpTo(2);
}
}.start();
pause(1000);
verify(slide1).stop();
verify(slide3).execute(any(Context.class));
}
@Test
public void testDuringSlide3_JumpToSlide1() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(100);
slideshow.next();
pause(100);
slideshow.next();
pause(100);
slideshow.jumpTo(0);
}
}.start();
pause(500);
verify(slide1).stop();
verify(slide3).execute(any(Context.class));
}
@Test
public void testDuringSlide1_PauseNext() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(100);
slideshow.pause();
pause(100);
slideshow.next();
}
}.start();
pause(1000);
// slide 1 should stop
verify(slide1, atLeast(1)).stop();
// slide 2 should never execute
verify(slide2,never()).execute(any(Context.class));
}
@Test
public void testDuringSlide1_PauseNextPlay() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(100);
slideshow.pause();
pause(100);
slideshow.next();
pause(100);
slideshow.play();
}
}.start();
pause(500);
// slide 1 should stop
verify(slide1,atLeast(1)).stop();
// slide 1 should execute only once (didn't get re-executed)
verify(slide1).execute(any(Context.class));
// slide 2 should execute
verify(slide2).execute(any(Context.class));
}
@Test
public void testDuringSlide1_PausePlay() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(100);
slideshow.pause();
pause(100);
slideshow.play();
}
}.start();
pause(800);
// slide 1 should stop
verify(slide1).stop();
// slide 1 should execute two times
verify(slide1, times(2)).execute(any(Context.class));
verify(slide2).execute(any(Context.class));
}
@Test
public void testDuringSlide1_PausePause() throws ActionExecutionException {
slideshow.start();
new Thread(){
public void run(){
pause(100);
slideshow.pause();
pause(100);
slideshow.pause();
}
}.start();
pause(800);
// slide 1 should stop
verify(slide1).stop();
// slide should execute only once
verify(slide1).execute(any(Context.class));
}
@Test
public void testDuringSlide1_ThrowException() throws ActionExecutionException {
((TestSlide) slide1).setThrowException(true);
slideshow.start();
pause(800);
verify(slide1).execute(any(Context.class));
verify(slide2, never()).execute(any(Context.class));
}
@Test
public void testDuringSlide2_ThrowException() throws ActionExecutionException {
((TestSlide) slide2).setThrowException(true);
slideshow.start();
pause(1200);
verify(slide1).execute(any(Context.class));
verify(slide2).execute(any(Context.class));
verify(slide3, never()).execute(any(Context.class));
}
@Test
public void testStartWithNoSlides(){
slideshow = new DefaultSlideShowController(context, new ArrayList<Slide>());
assertThat(slideshow.hasNext(), equalTo(false));
assertThat(slideshow.hasPrevious(), equalTo(false));
assertThat(slideshow.isPaused(), equalTo(false));
}
}