TreeAdapter extends PowerAdapter { public void setAutoExpand(boolean autoExpand) { mAutoExpand = autoExpand; } TreeAdapter(@NonNull PowerAdapter rootAdapter, @NonNull ChildAdapterSupplier childAdapterSupplier); @NonNull Parcelable saveInstanceState(); void restoreInstanceState(@Nullable Parcelable parcelable); boolean isAutoExpand(); void setAutoExpand(boolean autoExpand); boolean isExpanded(int position); void setExpanded(int position, boolean expanded); boolean toggleExpanded(int position); void setAllExpanded(boolean expanded); @Override int getItemCount(); @Override boolean hasStableIds(); @Override long getItemId(int position); @Override boolean isEnabled(int position); @NonNull @Override Object getItemViewType(int position); @NonNull @Override View newView(@NonNull ViewGroup parent, @NonNull Object viewType); @Override void bindView(
            @NonNull Container container,
            @NonNull View view,
            @NonNull Holder holder,
            @NonNull List<Object> payloads
    );  }
@Test public void treeRegistersObserversOnChildAdaptersWhenFirstExternalObserverRegisters() { final PowerAdapter childAdapter = mock(PowerAdapter.class); TreeAdapter treeAdapter = new TreeAdapter(new FakeAdapter(3), new ChildAdapterSupplier() { @NonNull @Override public PowerAdapter get(int position) { return childAdapter; } }); treeAdapter.setAutoExpand(true); treeAdapter.registerDataObserver(mock(DataObserver.class)); verify(childAdapter, times(3)).registerDataObserver(any(DataObserver.class)); }
@Test public void treeUnregistersObserversFromChildAdaptersWhenLastExternalObserverUnregisters() { final List<PowerAdapter> childAdapters = ImmutableList.of( mock(PowerAdapter.class), mock(PowerAdapter.class), mock(PowerAdapter.class) ); TreeAdapter treeAdapter = new TreeAdapter(mRootAdapter, new ChildAdapterSupplier() { @NonNull @Override public PowerAdapter get(int position) { return childAdapters.get(position); } }); treeAdapter.setAutoExpand(true); DataObserver observer = mock(DataObserver.class); treeAdapter.registerDataObserver(observer); treeAdapter.unregisterDataObserver(observer); for (PowerAdapter adapter : childAdapters) { ArgumentCaptor<DataObserver> captor = ArgumentCaptor.forClass(DataObserver.class); verify(adapter).registerDataObserver(captor.capture()); verify(adapter).unregisterDataObserver(eq(captor.getValue())); } }
@Test public void treeRegistersObserverOnRootAdapterWhenFirstExternalObserverRegisters() { PowerAdapter rootAdapter = mock(PowerAdapter.class); ChildAdapterSupplier adapterSupplier = mock(ChildAdapterSupplier.class); when(adapterSupplier.get(anyInt())).thenReturn(mock(PowerAdapter.class)); TreeAdapter treeAdapter = new TreeAdapter(rootAdapter, adapterSupplier); treeAdapter.setAutoExpand(true); treeAdapter.registerDataObserver(mock(DataObserver.class)); verify(rootAdapter).registerDataObserver(any(DataObserver.class)); }
@Test public void treeUnregistersObserverFromRootAdapterWhenLastExternalObserverUnregisters() { ChildAdapterSupplier adapterSupplier = mock(ChildAdapterSupplier.class); when(adapterSupplier.get(anyInt())).thenReturn(mock(PowerAdapter.class)); PowerAdapter rootAdapter = mock(PowerAdapter.class); TreeAdapter treeAdapter = new TreeAdapter(rootAdapter, adapterSupplier); treeAdapter.setAutoExpand(true); DataObserver observer = mock(DataObserver.class); treeAdapter.registerDataObserver(observer); treeAdapter.unregisterDataObserver(observer); ArgumentCaptor<DataObserver> captor = ArgumentCaptor.forClass(DataObserver.class); verify(rootAdapter).registerDataObserver(captor.capture()); verify(rootAdapter).unregisterDataObserver(eq(captor.getValue())); }
@Test public void rootChangeUnregistersFromPreviousChildAdapterIfExpanded() { FakeAdapter rootAdapter = new FakeAdapter(1); PowerAdapter oldChildAdapter = mock(PowerAdapter.class); final AtomicReference<PowerAdapter> childAdapterRef = new AtomicReference<>(oldChildAdapter); TreeAdapter treeAdapter = new TreeAdapter(rootAdapter, new ChildAdapterSupplier() { @NonNull @Override public PowerAdapter get(int position) { return childAdapterRef.get(); } }); treeAdapter.setAutoExpand(true); treeAdapter.registerDataObserver(mObserver); childAdapterRef.getAndSet(EMPTY); rootAdapter.change(0, 1, null); ArgumentCaptor<DataObserver> captor = ArgumentCaptor.forClass(DataObserver.class); verify(oldChildAdapter).registerDataObserver(captor.capture()); verify(oldChildAdapter).unregisterDataObserver(eq(captor.getValue())); }
@Test public void rootChangeRemovesAndInsertsChildItemsIfExpandedAndChildAdapterInstanceChanges() { TreeAdapter treeAdapter = new TreeAdapter(mRootAdapter, new ChildAdapterSupplier() { @NonNull @Override public PowerAdapter get(int position) { return new FakeAdapter(3); } }); treeAdapter.setAutoExpand(true); treeAdapter.registerDataObserver(mock(DataObserver.class)); DataObserver observer = mock(DataObserver.class); treeAdapter.registerDataObserver(observer); mRootAdapter.change(1, 1, null); verify(observer).onItemRangeChanged(4, 1, null); verify(observer).onItemRangeRemoved(5, 3); verify(observer).onItemRangeInserted(5, 3); verifyNoMoreInteractions(observer); }
@Test public void childInsertionGeneratesTreeInsertion() { final FakeAdapter childAdapter = new FakeAdapter(3); TreeAdapter treeAdapter = new TreeAdapter(new FakeAdapter(1), new ChildAdapterSupplier() { @NonNull @Override public PowerAdapter get(int position) { return childAdapter; } }); treeAdapter.setAutoExpand(true); treeAdapter.registerDataObserver(mock(DataObserver.class)); DataObserver observer = mock(DataObserver.class); treeAdapter.registerDataObserver(observer); childAdapter.append(2); verify(observer).onItemRangeInserted(4, 2); verifyNoMoreInteractions(observer); }
@Test public void childRemovalGeneratesTreeRemoval() { final FakeAdapter childAdapter = new FakeAdapter(3); TreeAdapter treeAdapter = new TreeAdapter(new FakeAdapter(1), new ChildAdapterSupplier() { @NonNull @Override public PowerAdapter get(int position) { return childAdapter; } }); treeAdapter.setAutoExpand(true); treeAdapter.registerDataObserver(mock(DataObserver.class)); DataObserver observer = mock(DataObserver.class); treeAdapter.registerDataObserver(observer); childAdapter.remove(1, 1); verify(observer).onItemRangeRemoved(2, 1); verifyNoMoreInteractions(observer); }