/*
Copyright 2014 Red Hat, Inc. and/or its affiliates.
This file is part of darcy-ui.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.redhat.darcy.ui;
import static com.redhat.darcy.ui.matchers.DarcyMatchers.present;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.matches;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import com.redhat.darcy.ui.api.Context;
import com.redhat.darcy.ui.api.Locator;
import com.redhat.darcy.ui.api.elements.Label;
import com.redhat.darcy.ui.internal.FindsById;
import com.redhat.darcy.ui.testing.doubles.AlwaysDisplayedLabel;
import com.redhat.darcy.ui.testing.doubles.NeverFoundElement;
import com.redhat.darcy.ui.testing.doubles.NeverFoundLabel;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
@RunWith(JUnit4.class)
public class BySequenceTest {
@Test
public void shouldKeepFindingElementsInSequenceUntilNextIsNotPresentStartingFromSomeIndex() {
TestContext mockContext = mock(TestContext.class);
Label label1 = new AlwaysDisplayedLabel();
Label label2 = new AlwaysDisplayedLabel();
Label label3 = new AlwaysDisplayedLabel();
Label label4 = new AlwaysDisplayedLabel();
when(mockContext.findById(Label.class, "1")).thenReturn(label1);
when(mockContext.findById(Label.class, "2")).thenReturn(label2);
when(mockContext.findById(Label.class, "3")).thenReturn(label3);
when(mockContext.findById(Label.class, "4")).thenReturn(label4);
when(mockContext.findById(Label.class, "5")).thenReturn(new NeverFoundLabel());
By.BySequence bySequence = By.sequence(i -> By.id(i.toString()), 1);
List<Label> found = bySequence.findAll(Label.class, mockContext);
assertThat(found, contains(label1, label2, label3, label4));
}
@Test
public void shouldStartWithIndexOf0ByDefault() {
TestContext mockContext = mock(TestContext.class);
when(mockContext.findById(Label.class, "0")).thenReturn(new NeverFoundLabel());
By.BySequence bySequence = By.sequence(i -> By.id(i.toString()));
List<Label> found = bySequence.findAll(Label.class, mockContext);
// do something to trigger actually looking up the elements
found.size();
verify(mockContext).findById(Label.class, "0");
verifyNoMoreInteractions(mockContext);
}
@Test
public void shouldFindFirstInSequenceWhenFindingSingleElementRegardlesOfIfItIsPresent() {
TestContext mockContext = mock(TestContext.class);
Label shouldBeFound = new NeverFoundLabel();
when(mockContext.findById(Label.class, "5")).thenReturn(shouldBeFound);
By.BySequence bySequence = By.sequence(i -> By.id(i.toString()), 5);
Label actuallyFound = bySequence.find(Label.class, mockContext);
assertThat(actuallyFound, equalTo(shouldBeFound));
assertThat(actuallyFound, is(not(present())));
}
@Test
public void shouldReturnLazilyEvaluatedList() {
TestContext mockContext = mock(TestContext.class);
when(mockContext.findById(Label.class, "0")).thenReturn(new NeverFoundLabel());
By.BySequence bySequence = By.sequence(i -> By.id(i.toString()));
List<Label> found = bySequence.findAll(Label.class, mockContext);
verifyZeroInteractions(mockContext);
}
@Test
public void shouldBeEquivalentToBySequencesThatShareEquivalentSequencesAndStartingIndexes() {
By.BySequence thingSequence = By.sequence(new IdCounter("thing_"), 1);
assertThat(thingSequence, equalTo(thingSequence));
assertThat(thingSequence, equalTo(By.sequence(new IdCounter("thing_"), 1)));
}
@Test
public void shouldNotBeEquivalentToAnythingElse() {
By.BySequence thingSequence = By.sequence(new IdCounter("thing_"), 1);
assertThat(thingSequence, not(equalTo(By.id("huh"))));
assertThat(thingSequence, not(equalTo(By.sequence(new IdCounter("thing_"), 0))));
assertThat(thingSequence, not(equalTo(By.sequence(i -> By.id(i.toString()), 1))));
}
@Test
public void shouldHaveEquivalentHashCodesForEquivalentSequences() {
By.BySequence thingSequence = By.sequence(new IdCounter("thing_"), 1);
assertThat(thingSequence.hashCode(),
equalTo(By.sequence(new IdCounter("thing_"), 1).hashCode()));
}
private static class IdCounter implements Function<Integer, Locator> {
private final String prefix;
private IdCounter(String prefix) {
this.prefix = prefix;
}
@Override
public Locator apply(Integer integer) {
return By.id(prefix + integer);
}
@Override
public boolean equals(Object o) {
if (o.getClass() != IdCounter.class) {
return false;
}
IdCounter that = (IdCounter) o;
return Objects.equals(that.prefix, this.prefix);
}
@Override
public int hashCode() {
return prefix != null ? prefix.hashCode() : 0;
}
}
private interface TestContext extends Context, FindsById {}
}