package com.alapshin.arctor.presenter.rx;


import com.alapshin.arctor.presenter.rx.delivery.DeliverLatest;

import org.junit.Test;

import java.util.concurrent.TimeUnit;

import rx.Observable;
import rx.observers.TestSubscriber;

import static org.assertj.core.api.Assertions.assertThat;

public class DeliverLatestTest {
    private static final int DELAY_IN_MILLISECONDS = 200;

    @Test
    public void emitWithAttachedView() {
        Observable<Boolean> view = Observable.just(true);
        DeliverLatest<Integer> transformer = new DeliverLatest<>(view);
        TestSubscriber<Integer> testSubscriber = new TestSubscriber<>();
        Observable.just(0)
                .compose(transformer)
                .subscribe(testSubscriber);
        testSubscriber.awaitTerminalEvent();
        testSubscriber.assertValue(0);
        testSubscriber.assertCompleted();
    }

    @Test
    public void emitLastWithAttachedView() {
        Observable<Boolean> view = Observable.just(true);
        DeliverLatest<Integer> transformer = new DeliverLatest<>(view);
        TestSubscriber<Integer> testSubscriber = new TestSubscriber<>();
        Observable.just(0, 1, 2)
                .compose(transformer)
                .subscribe(testSubscriber);
        testSubscriber.awaitTerminalEvent();
        testSubscriber.assertValues(0, 1, 2);
        testSubscriber.assertCompleted();
    }

    @Test
    public void doesNotEmitWithDetachedView() {
        Observable<Boolean> view = Observable.just(false);
        DeliverLatest<Integer> transformer = new DeliverLatest<>(view);
        TestSubscriber<Integer> testSubscriber = new TestSubscriber<>();
        Observable.just(0)
                .compose(transformer)
                .subscribe(testSubscriber);
        testSubscriber.awaitTerminalEvent();
        testSubscriber.assertNoValues();
    }

    @Test
    public void doesNotEmitWithNeverAttachedView() {
        Observable<Boolean> view = Observable.never();
        DeliverLatest<Integer> transformer = new DeliverLatest<>(view);
        TestSubscriber<Integer> testSubscriber = new TestSubscriber<>();
        Observable.just(0)
                .compose(transformer)
                .subscribe(testSubscriber);
        testSubscriber.awaitTerminalEvent(DELAY_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
        testSubscriber.assertNoValues();
    }

    @Test
    public void emitLastAfterViewAttachment() {
        Observable<Boolean> view = Observable.just(true)
                .delaySubscription(DELAY_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
        DeliverLatest<Integer> transformer = new DeliverLatest<>(view);
        TestSubscriber<Integer> testSubscriber = new TestSubscriber<>();
        Observable.just(0, 1, 2)
                .compose(transformer)
                .subscribe(testSubscriber);
        testSubscriber.awaitTerminalEvent();
        testSubscriber.assertValue(2);
        testSubscriber.assertCompleted();
    }

    @Test
    public void emitErrorWithAttachedView() {
        Observable<Boolean> view = Observable.just(true);
        DeliverLatest<Object> transformer = new DeliverLatest<>(view);
        TestSubscriber<Object> testSubscriber = new TestSubscriber<>();
        Observable.error(new RuntimeException())
                .compose(transformer)
                .subscribe(testSubscriber);
        testSubscriber.awaitTerminalEvent();
        testSubscriber.assertError(RuntimeException.class);
    }

    @Test
    public void doesNotEmitErrorWithDetachedView() {
        Observable<Boolean> view = Observable.just(false);
        DeliverLatest<Object> transformer = new DeliverLatest<>(view);
        TestSubscriber<Object> testSubscriber = new TestSubscriber<>();
        Observable.error(new RuntimeException())
                .compose(transformer)
                .subscribe(testSubscriber);
        testSubscriber.awaitTerminalEvent(DELAY_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
        testSubscriber.assertNoErrors();
    }

    @Test
    public void doesNotEmitErrorWithNeverAttachedView() {
        Observable<Boolean> view = Observable.never();
        DeliverLatest<Object> transformer = new DeliverLatest<>(view);
        TestSubscriber<Object> testSubscriber = new TestSubscriber<>();
        Observable.error(new RuntimeException())
                .compose(transformer)
                .subscribe(testSubscriber);
        testSubscriber.awaitTerminalEvent(DELAY_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
        testSubscriber.assertNoErrors();
    }

    @Test
    public void emitErrorAfterViewAttachment() {
        Observable<Boolean> view = Observable.just(true)
                .delay(DELAY_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
        DeliverLatest<Object> transformer = new DeliverLatest<>(view);
        TestSubscriber<Object> testSubscriber = new TestSubscriber<>();
        Observable.error(new RuntimeException())
                .compose(transformer)
                .subscribe(testSubscriber);
        testSubscriber.awaitTerminalEvent();
        testSubscriber.assertError(RuntimeException.class);
    }

    @Test
    public void emitValueFromEndlessAfterViewAttachment() {
        Observable<Boolean> view = Observable.just(true)
                .delay(DELAY_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
        DeliverLatest<Object> transformer = new DeliverLatest<>(view);
        TestSubscriber<Object> testSubscriber = new TestSubscriber<>();
        Observable.interval(0, 100, TimeUnit.MILLISECONDS)
                .compose(transformer)
                .subscribe(testSubscriber);
        testSubscriber.awaitTerminalEvent(500, TimeUnit.MILLISECONDS);
        testSubscriber.assertNotCompleted();
        assertThat(testSubscriber.getOnNextEvents()).isNotEmpty();
    }
}

@@ -222,16 +222,85 @@
 scriber;
+%0Aimport rx.schedulers.Schedulers;%0Aimport rx.schedulers.TestScheduler;
 %0A%0Aimport
@@ -2476,32 +2476,162 @@
 wAttachment() %7B%0A
+        TestScheduler testScheduler = Schedulers.test();%0A        TestSubscriber%3CInteger%3E testSubscriber = new TestSubscriber%3C%3E();%0A
         Observab
@@ -2697,20 +2697,8 @@
 elay
-Subscription
 (DEL
@@ -2730,32 +2730,47 @@
 nit.MILLISECONDS
+, testScheduler
 );%0A        Deliv
@@ -2832,81 +2832,8 @@
 w);%0A
-        TestSubscriber%3CInteger%3E testSubscriber = new TestSubscriber%3C%3E();%0A
     
@@ -2935,32 +2935,115 @@
 estSubscriber);%0A
+        testScheduler.advanceTimeBy(DELAY_IN_MILLISECONDS, TimeUnit.MILLISECONDS);%0A
         testSubs
@@ -4252,32 +4252,104 @@
 ttachedView() %7B%0A
+        TestSubscriber%3CObject%3E testSubscriber = new TestSubscriber%3C%3E();%0A
         Observab
@@ -4462,80 +4462,8 @@
 w);%0A
-        TestSubscriber%3CObject%3E testSubscriber = new TestSubscriber%3C%3E();%0A
     
@@ -5360,32 +5360,162 @@
 wAttachment() %7B%0A
+        TestScheduler testScheduler = Schedulers.test();%0A        TestSubscriber%3CObject%3E testSubscriber = new TestSubscriber%3C%3E();%0A%0A
         Observab
@@ -5614,32 +5614,47 @@
 nit.MILLISECONDS
+, testScheduler
 );%0A        Deliv
@@ -5715,80 +5715,8 @@
 w);%0A
-        TestSubscriber%3CObject%3E testSubscriber = new TestSubscriber%3C%3E();%0A
     
@@ -5768,16 +5768,31 @@
 ISECONDS
+, testScheduler
 )%0A      
@@ -5884,36 +5884,30 @@
 estS
-ubscriber.awaitTerminalEvent
+cheduler.advanceTimeBy
 (500

Fix flaky tests by using TestScheduler