Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List change event inconsistencies #51

Open
JeffFaer opened this issue Jan 4, 2016 · 1 comment
Open

List change event inconsistencies #51

JeffFaer opened this issue Jan 4, 2016 · 1 comment

Comments

@JeffFaer
Copy link

JeffFaer commented Jan 4, 2016

I've noticed some strange behavior with list change events when using EventStreams or LiveList.

import static org.hamcrest.Matchers.contains;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.verify;

import java.util.function.Consumer;

import javafx.beans.Observable;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.reactfx.EventStreams;
import org.reactfx.collection.ListChange;
import org.reactfx.collection.LiveList;

@RunWith(MockitoJUnitRunner.class)
public class LiveListUpdateTest {
  private static class Data {
    private final Property<String> string = new SimpleObjectProperty<>();

    public String getString() {
      return string.getValue();
    }

    public Property<String> stringProperty() {
      return string;
    }
  }

  @Captor
  ArgumentCaptor<ListChangeListener.Change<? extends Data>> originalChange;
  @Captor
  ArgumentCaptor<ListChangeListener.Change<? extends Data>> eventStreamChange;
  @Captor
  ArgumentCaptor<ListChange<? extends Data>> liveListChange;
  @Captor
  ArgumentCaptor<ListChangeListener.Change<? extends String>> mappedChange;

  @Mock
  ListChangeListener<? super Data> originalListener;
  @Mock
  Consumer<ListChangeListener.Change<? extends Data>> eventStreamListener;
  @Mock
  Consumer<ListChange<? extends Data>> liveListListener;
  @Mock
  ListChangeListener<? super String> mappedListener;

  Data data;
  ObservableList<Data> updateableList;
  ObservableList<String> mappedList;

  @Before
  public void before() {
    data = new Data();
    updateableList = FXCollections.observableArrayList(d -> new Observable[] { d.stringProperty() });
    updateableList.add(data);

    mappedList = LiveList.map(updateableList, Data::getString);
  }

  @Test
  public void initialChangeState() {
    updateableList.addListener(originalListener);
    EventStreams.changesOf(updateableList).subscribe(eventStreamListener);

    data.stringProperty().setValue("foo");

    verify(originalListener).onChanged(originalChange.capture());
    assertTrue(originalChange.getValue().next());

    verify(eventStreamListener).accept(eventStreamChange.capture());
    assertTrue(eventStreamChange.getValue().next()); // Fails
  }

  @Test
  public void liveListShouldNotInvalidateInitialChangeState() {
    updateableList.addListener(originalListener);
    LiveList.changesOf(updateableList).subscribe(liveListListener);

    data.stringProperty().setValue("foo");

    verify(originalListener).onChanged(originalChange.capture());
    assertTrue(originalChange.getValue().next()); // Fails

    verify(liveListListener).accept(liveListChange.capture());
    assertEquals(1, liveListChange.getValue().getModificationCount());
  }

  @Test
  public void mappedUpdates() {
    updateableList.addListener(originalListener);
    mappedList.addListener(mappedListener);

    data.stringProperty().setValue("foo");
    assertThat(mappedList, contains("foo"));

    verify(originalListener).onChanged(originalChange.capture());
    assertTrue(originalChange.getValue().next()); // Fails
    assertTrue(originalChange.getValue().wasUpdated());
    assertFalse(originalChange.getValue().next());

    verify(mappedListener).onChanged(mappedChange.capture());
    assertTrue(originalChange.getValue().next()); // Fails
    assertTrue(mappedChange.getValue().wasUpdated()); // Fails
    assertFalse(originalChange.getValue().next());
  }
}
@TomasMikula
Copy link
Owner

Hi Jeffrey, thank you for the report and test cases. I could include them in ReactFX tests, if you could rewrite them without using Mockito.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants