/*
* Copyright 2015 Rayco AraƱa
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.raycoarana.baindo.properties;
import android.view.View;
import com.raycoarana.baindo.BindableSource;
import com.raycoarana.baindo.WorkDispatcher;
import com.raycoarana.baindo.WorkDispatcherHelper;
import com.raycoarana.baindo.observables.AbstractProperty;
import com.raycoarana.baindo.test.UnitTestSuite;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import java.util.Observer;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public abstract class AbstractBindTest<T, Bind extends BaseBind<T, AbstractProperty<T>>> extends UnitTestSuite {
protected final T mDefaultValue;
protected final T mNewValue;
@Mock
protected WorkDispatcher mWorkDispatcher;
@Mock
protected BindableSource mBindableSource;
@Mock
protected AbstractProperty<T> mProperty;
@Captor
private ArgumentCaptor<Observer> mObserverArgumentCaptor;
protected Bind mBaseBind;
protected View mView;
private boolean mWriteNotSupported;
public AbstractBindTest(T defaultValue, T newValue, boolean writeSupported) {
mDefaultValue = defaultValue;
mNewValue = newValue;
mWriteNotSupported = !writeSupported;
}
@Before
public void setUp() {
super.setUp();
when(mProperty.getValue()).thenReturn(mDefaultValue);
}
@Test
public void shouldUpdateViewWhenPropertyChanges() {
givenABaseBind();
givenACompatibleView();
if(mWriteNotSupported) {
givenThatBindIsBindedAsReadOnly();
} else {
givenThatBindIsBindedAsReadWrite();
}
whenPropertyUpdated();
thenViewIsChanged();
}
@Test(expected = IllegalStateException.class)
public void shouldFailWhenTryingToBindToIncompatibleView() {
givenABaseBind();
givenSomeView();
givenThatBindIsBindedAsReadWrite();
}
@Test
public void shouldNotUpdateViewIfWriteOnly() {
givenABaseBind();
givenACompatibleView();
try {
givenThatBindIsBindedAsWriteOnly();
whenPropertyUpdated();
thenViewIsNotChanged();
} catch (IllegalStateException ex) {
assertTrue(ex.getMessage(), mWriteNotSupported);
}
}
protected void givenABaseBind() {
WorkDispatcherHelper.setup(mWorkDispatcher);
mBaseBind = getBind();
}
protected abstract Bind getBind();
private void givenSomeView() {
mView = mock(View.class);
}
protected void givenThatBindIsBindedAsReadWrite() {
mBaseBind.of(mView).to(mProperty).readWrite();
}
protected void givenThatBindIsBindedAsReadOnly() {
mBaseBind.of(mView).to(mProperty).readOnly();
}
protected void givenThatBindIsBindedAsWriteOnly() {
mBaseBind.of(mView).to(mProperty).writeOnly();
}
protected void givenThatIsUnbinded() {
mBaseBind.unbind();
}
protected abstract void givenACompatibleView();
protected void whenPropertyUpdated() {
verify(mProperty, atMost(1)).addObserver(mObserverArgumentCaptor.capture());
if(mObserverArgumentCaptor.getAllValues().size() > 0) {
when(mProperty.getValue()).thenReturn(mNewValue);
Observer observer = mObserverArgumentCaptor.getValue();
observer.update(mProperty, mNewValue);
}
}
private void thenViewIsChanged() {
verifyViewChanged(mDefaultValue);
verifyViewChanged(mNewValue);
}
protected void thenViewIsNotChanged() {
verifyViewNotChanged(mDefaultValue);
verifyViewNotChanged(mNewValue);
}
protected abstract void verifyViewChanged(T value);
protected abstract void verifyViewNotChanged(T value);
}