diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/items/grid/GridItemDecoration.java b/app/src/main/java/it/niedermann/owncloud/notes/main/items/grid/GridItemDecoration.java index 2cfcee88..01743638 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/items/grid/GridItemDecoration.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/items/grid/GridItemDecoration.java @@ -20,6 +20,9 @@ public class GridItemDecoration extends SectionItemDecoration { public GridItemDecoration(@NonNull ItemAdapter adapter, int spanCount, @Px int sectionLeft, @Px int sectionTop, @Px int sectionRight, @Px int sectionBottom, @Px int gutter) { super(adapter, sectionLeft, sectionTop, sectionRight, sectionBottom); + if(spanCount < 1) { + throw new IllegalArgumentException("Requires at least one span"); + } this.spanCount = spanCount; this.adapter = adapter; this.gutter = gutter; diff --git a/app/src/test/java/it/niedermann/owncloud/notes/main/items/grid/GridItemDecorationTest.java b/app/src/test/java/it/niedermann/owncloud/notes/main/items/grid/GridItemDecorationTest.java new file mode 100644 index 00000000..8fb9ca45 --- /dev/null +++ b/app/src/test/java/it/niedermann/owncloud/notes/main/items/grid/GridItemDecorationTest.java @@ -0,0 +1,103 @@ +package it.niedermann.owncloud.notes.main.items.grid; + +import android.graphics.Rect; +import android.os.Build; +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.util.Arrays; + +import it.niedermann.owncloud.notes.main.items.ItemAdapter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +@Config(sdk = {Build.VERSION_CODES.P}) +public class GridItemDecorationTest { + + private final ItemAdapter itemAdapter = mock(ItemAdapter.class); + private final RecyclerView recyclerView = mock(RecyclerView.class); + private final View view = mock(View.class); + private final StaggeredGridLayoutManager.LayoutParams layoutParams = mock(StaggeredGridLayoutManager.LayoutParams.class); + + @Test + public void getItemOffsets() { + when(view.getLayoutParams()).thenReturn(layoutParams); + when(itemAdapter.getFirstPositionOfViewType(anyInt())).thenReturn(0); + when(itemAdapter.getItemViewType(anyInt())).then((arg) -> Arrays.asList(0, 4, 9).contains(arg.getArgument(0, Integer.class)) + ? ItemAdapter.TYPE_SECTION + : ItemAdapter.TYPE_NOTE_ONLY_TITLE); + + assertThrows("Requires at least one column", IllegalArgumentException.class, () -> new GridItemDecoration(itemAdapter, 0, 5, 5, 5, 5, 5)); + + final GridItemDecoration oneColumn = new GridItemDecoration(itemAdapter, 1, 5, 5, 5, 5, 5); + + testAssertion(oneColumn, 0, 0, true, 5, 5, 5, 5); + testAssertion(oneColumn, 0, 1, false, 0, 5, 5, 5); + testAssertion(oneColumn, 0, 2, false, 0, 5, 5, 5); + testAssertion(oneColumn, 0, 3, false, 0, 5, 5, 5); + testAssertion(oneColumn, 0, 4, true, 5, 5, 5, 5); + testAssertion(oneColumn, 0, 5, false, 0, 5, 5, 5); + testAssertion(oneColumn, 0, 6, false, 0, 5, 5, 5); + testAssertion(oneColumn, 0, 7, false, 0, 5, 5, 5); + testAssertion(oneColumn, 0, 8, false, 0, 5, 5, 5); + testAssertion(oneColumn, 0, 9, true, 5, 5, 5, 5); + + final GridItemDecoration twoColumns = new GridItemDecoration(itemAdapter, 2, 5, 5, 5, 5, 5); + + testAssertion(twoColumns, 0, 0, true, 5, 5, 5, 5); + testAssertion(twoColumns, 0, 1, false, 0, 5, 5, 5); + testAssertion(twoColumns, 1, 2, false, 0, 0, 5, 5); + testAssertion(twoColumns, 0, 3, false, 0, 5, 5, 5); + testAssertion(twoColumns, 0, 4, true, 5, 5, 5, 5); + testAssertion(twoColumns, 0, 5, false, 0, 5, 5, 5); + testAssertion(twoColumns, 1, 6, false, 0, 0, 5, 5); + testAssertion(twoColumns, 0, 7, false, 0, 5, 5, 5); + testAssertion(twoColumns, 0, 8, false, 0, 5, 5, 5); + testAssertion(twoColumns, 0, 9, true, 5, 5, 5, 5); + + final GridItemDecoration threeColumns = new GridItemDecoration(itemAdapter, 3, 5, 5, 5, 5, 5); + + testAssertion(threeColumns, 0, 0, true, 5, 5, 5, 5); + testAssertion(threeColumns, 0, 1, false, 0, 5, 5, 5); + testAssertion(threeColumns, 1, 2, false, 0, 0, 5, 5); + testAssertion(threeColumns, 2, 3, false, 0, 0, 5, 5); + testAssertion(threeColumns, 0, 4, true, 5, 5, 5, 5); + testAssertion(threeColumns, 0, 5, false, 0, 5, 5, 5); + testAssertion(threeColumns, 1, 6, false, 0, 0, 5, 5); + testAssertion(threeColumns, 2, 7, false, 0, 0, 5, 5); + testAssertion(threeColumns, 0, 8, false, 0, 5, 5, 5); + testAssertion(threeColumns, 0, 9, true, 5, 5, 5, 5); + } + + @SuppressWarnings("SameParameterValue") + private void testAssertion(GridItemDecoration gid, int spanIndex, int position, boolean fullSpan, int top, int left, int right, int bottom) { + when(layoutParams.getSpanIndex()).thenReturn(spanIndex); + when(recyclerView.getChildAdapterPosition(any())).thenReturn(position); + final Rect result = new Rect(); + gid.getItemOffsets(result, view, recyclerView, mock(RecyclerView.State.class)); + + if (fullSpan) { + verify(layoutParams).setFullSpan(true); + } + reset(layoutParams); + assertEquals(top, result.top); + assertEquals(left, result.left); + assertEquals(right, result.right); + assertEquals(bottom, result.bottom); + } +} \ No newline at end of file