package com.airbnb.epoxy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
import java.util.List;
import static com.airbnb.epoxy.ModelTestUtils.addModels;
import static com.airbnb.epoxy.ModelTestUtils.changeValue;
import static com.airbnb.epoxy.ModelTestUtils.remove;
import static junit.framework.Assert.assertEquals;
/**
* Tests that changes to the models via notify calls besides
* {@link EpoxyAdapter#notifyModelsChanged()}
* will properly update the model state maintained by the differ.
*/
@Config(sdk = 21, manifest = TestRunner.MANIFEST_PATH)
@RunWith(TestRunner.class)
public class DifferNotifyTest {
private static final int INITIAL_MODEL_COUNT = 20;
private static final boolean SHOW_LOGS = false;
private final TestObserver testObserver = new TestObserver(SHOW_LOGS);
private final TestAdapter adapter = new TestAdapter();
private final List<EpoxyModel<?>> models = adapter.models;
@Test(expected = UnsupportedOperationException.class)
public void notifyChange() {
adapter.notifyDataSetChanged();
}
@Test
public void notifyAddedToEmpty() {
addModels(models);
adapter.notifyItemRangeInserted(0, models.size());
assertCorrectness();
}
@Test
public void notifyAddedToStart() {
addInitialModels();
addModels(models, 0);
adapter.notifyItemRangeInserted(0, models.size() - INITIAL_MODEL_COUNT);
assertCorrectness();
}
@Test
public void notifyAddedToEnd() {
addInitialModels();
addModels(models, INITIAL_MODEL_COUNT);
adapter.notifyItemRangeInserted(INITIAL_MODEL_COUNT, models.size() - INITIAL_MODEL_COUNT);
assertCorrectness();
}
@Test
public void notifyAddedToMiddle() {
addInitialModels();
addModels(models, INITIAL_MODEL_COUNT / 2);
adapter.notifyItemRangeInserted(INITIAL_MODEL_COUNT / 2, models.size() - INITIAL_MODEL_COUNT);
assertCorrectness();
}
@Test
public void notifyRemoveAll() {
addInitialModels();
models.clear();
adapter.notifyItemRangeRemoved(0, INITIAL_MODEL_COUNT);
assertCorrectness();
}
@Test
public void notifyRemoveStart() {
addInitialModels();
remove(models, 0, INITIAL_MODEL_COUNT / 2);
adapter.notifyItemRangeRemoved(0, INITIAL_MODEL_COUNT / 2);
assertCorrectness();
}
@Test
public void notifyRemoveMiddle() {
addInitialModels();
remove(models, INITIAL_MODEL_COUNT / 3, INITIAL_MODEL_COUNT / 3);
adapter.notifyItemRangeRemoved(INITIAL_MODEL_COUNT / 3, INITIAL_MODEL_COUNT / 3);
assertCorrectness();
}
@Test
public void notifyRemoveEnd() {
addInitialModels();
remove(models, INITIAL_MODEL_COUNT / 2, INITIAL_MODEL_COUNT / 2);
adapter.notifyItemRangeRemoved(INITIAL_MODEL_COUNT / 2, INITIAL_MODEL_COUNT / 2);
assertCorrectness();
}
@Test
public void notifyFrontMovedToEnd() {
addInitialModels();
EpoxyModel<?> modelToMove = models.remove(0);
models.add(modelToMove);
adapter.notifyItemMoved(0, INITIAL_MODEL_COUNT - 1);
assertCorrectness();
}
@Test
public void notifyEndMovedToFront() {
addInitialModels();
EpoxyModel<?> modelToMove = models.remove(INITIAL_MODEL_COUNT - 1);
models.add(0, modelToMove);
adapter.notifyItemMoved(INITIAL_MODEL_COUNT - 1, 0);
assertCorrectness();
}
@Test
public void notifyMiddleMovedToEnd() {
addInitialModels();
EpoxyModel<?> modelToMove = models.remove(INITIAL_MODEL_COUNT / 2);
models.add(modelToMove);
adapter.notifyItemMoved(INITIAL_MODEL_COUNT / 2, INITIAL_MODEL_COUNT - 1);
assertCorrectness();
}
@Test
public void notifyMiddleMovedToFront() {
addInitialModels();
EpoxyModel<?> modelToMove = models.remove(INITIAL_MODEL_COUNT / 2);
models.add(0, modelToMove);
adapter.notifyItemMoved(INITIAL_MODEL_COUNT / 2, 0);
assertCorrectness();
}
@Test
public void notifyValuesUpdated() {
addInitialModels();
int numModelsUpdated = 0;
for (int i = INITIAL_MODEL_COUNT / 3; i < INITIAL_MODEL_COUNT * 2 / 3; i++) {
changeValue(models.get(i));
numModelsUpdated++;
}
adapter.notifyItemRangeChanged(INITIAL_MODEL_COUNT / 3, numModelsUpdated);
assertCorrectness();
}
private void addInitialModels() {
addModels(INITIAL_MODEL_COUNT, models);
adapter.notifyModelsChanged();
}
private void assertCorrectness() {
testObserver.operationCount = 0;
adapter.registerAdapterDataObserver(testObserver);
adapter.notifyModelsChanged();
adapter.unregisterAdapterDataObserver(testObserver);
assertEquals("Should not have any operations", 0, testObserver.operationCount);
}
}