-
Notifications
You must be signed in to change notification settings - Fork 168
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
301905f
commit ae50160
Showing
1 changed file
with
296 additions
and
0 deletions.
There are no files selected for viewing
296 changes: 296 additions & 0 deletions
296
subprojects/testfx-core/src/test/java/org/testfx/util/DebugUtilsTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,296 @@ | ||
/* | ||
* Copyright 2013-2014 SmartBear Software | ||
* Copyright 2014-2017 The TestFX Contributors | ||
* | ||
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the | ||
* European Commission - subsequent versions of the EUPL (the "Licence"); You may | ||
* not use this work except in compliance with the Licence. | ||
* | ||
* You may obtain a copy of the Licence at: | ||
* http://ec.europa.eu/idabc/eupl.html | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed | ||
* under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR | ||
* CONDITIONS OF ANY KIND, either express or implied. See the Licence for the | ||
* specific language governing permissions and limitations under the Licence. | ||
*/ | ||
package org.testfx.util; | ||
|
||
import java.util.concurrent.TimeoutException; | ||
import java.util.function.Function; | ||
import java.util.function.UnaryOperator; | ||
|
||
import javafx.beans.property.SimpleBooleanProperty; | ||
import javafx.scene.Scene; | ||
import javafx.scene.input.KeyCode; | ||
import javafx.scene.input.MouseButton; | ||
import javafx.scene.layout.Region; | ||
import javafx.stage.Stage; | ||
|
||
import org.hamcrest.BaseMatcher; | ||
import org.hamcrest.Description; | ||
import org.hamcrest.Matcher; | ||
import org.junit.After; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.testfx.TestFXRule; | ||
import org.testfx.api.FxAssert; | ||
import org.testfx.api.FxToolkit; | ||
import org.testfx.cases.TestCaseBase; | ||
import org.testfx.service.support.FiredEvents; | ||
|
||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.hamcrest.Matchers.is; | ||
import static org.testfx.util.DebugUtils.compose; | ||
import static org.testfx.util.DebugUtils.insertHeader; | ||
import static org.testfx.util.DebugUtils.runCode; | ||
import static org.testfx.util.DebugUtils.showFiredEvents; | ||
import static org.testfx.util.DebugUtils.showKeysPressedAtTestFailure; | ||
import static org.testfx.util.DebugUtils.showMouseButtonsPressedAtTestFailure; | ||
|
||
public class DebugUtilsTest extends TestCaseBase { | ||
|
||
private static final String TAB = " "; | ||
|
||
private static final MouseButton MOUSE_BUTTON = MouseButton.PRIMARY; | ||
private static final KeyCode KEY = KeyCode.A; | ||
|
||
@Rule | ||
public TestFXRule testFXRule = new TestFXRule(); | ||
|
||
@After | ||
public void cleanup() { | ||
release(KEY); | ||
release(MOUSE_BUTTON); | ||
} | ||
|
||
@Test | ||
public void composingMessageWithNoArgs() { | ||
// when: | ||
AssertionError error = getThrownErrorPostMapper(compose()); | ||
|
||
// then: | ||
assertThat(error.getMessage(), hasAddedTextEqualTo("")); | ||
} | ||
|
||
@Test | ||
public void composingMessageWithOneArg() { | ||
// given: | ||
String text = "text"; | ||
|
||
// when: | ||
AssertionError error = getThrownErrorPostMapper(compose(sb -> sb.append(text))); | ||
|
||
// then: | ||
assertThat(error.getMessage(), hasAddedTextEqualTo(text)); | ||
} | ||
|
||
@Test | ||
public void composingMessageWithMultipleArgs() { | ||
// given: | ||
String text = "text"; | ||
String other = "other"; | ||
|
||
// when: | ||
AssertionError error = getThrownErrorPostMapper( | ||
compose( | ||
sb -> sb.append(text), | ||
sb -> sb.append(other) | ||
) | ||
); | ||
|
||
// then: | ||
assertThat(error.getMessage(), hasAddedTextThatContains(text + other)); | ||
} | ||
|
||
@Test | ||
public void runCodeBlock() { | ||
// given: | ||
SimpleBooleanProperty prop = new SimpleBooleanProperty(false); | ||
|
||
// when: | ||
getThrownErrorPostMapper( | ||
runCode(() -> prop.set(true)) | ||
); | ||
|
||
// then: | ||
assertThat(prop.get(), is(true)); | ||
} | ||
|
||
@Test | ||
public void insertHeaderIntoErrorMessage() { | ||
// given: | ||
String header = "header"; | ||
|
||
// when: | ||
AssertionError error = getThrownErrorPostMapper(insertHeader(header, TAB)); | ||
|
||
// then: | ||
assertThat(error.getMessage(), hasAddedTextEqualTo("\n\n" + TAB + header)); | ||
} | ||
|
||
@Test | ||
public void showPressedMouseButtonsInErrorMessage() throws TimeoutException { | ||
// given: | ||
Stage stage = FxToolkit.toolkitContext().getRegisteredStage(); | ||
moveTo(stage) | ||
.moveBy(10, 10) | ||
.press(MOUSE_BUTTON); | ||
|
||
// when: | ||
AssertionError error = getThrownErrorPostMapper(showMouseButtonsPressedAtTestFailure(this, TAB)); | ||
|
||
// then: | ||
assertThat(error.getMessage(), hasAddedTextThatContains(MOUSE_BUTTON.name())); | ||
} | ||
|
||
@Test | ||
public void showPressedKeysInErrorMessage() throws TimeoutException { | ||
// given: | ||
Stage stage = FxToolkit.toolkitContext().getRegisteredStage(); | ||
moveTo(stage) | ||
.moveBy(10, 10) | ||
.press(KEY); | ||
|
||
// when: | ||
AssertionError error = getThrownErrorPostMapper(showKeysPressedAtTestFailure(this, TAB)); | ||
|
||
// then: | ||
assertThat(error.getMessage(), hasAddedTextThatContains(KEY.name())); | ||
} | ||
|
||
@Test | ||
public void showFiredEventsInErrorMessage() throws TimeoutException { | ||
// given: | ||
Stage stage = FxToolkit.setupStage(stage0 -> stage0.setScene(new Scene(new Region(), 300, 300))); | ||
interact(stage::show); | ||
moveTo(stage).moveBy(20, 20); | ||
|
||
// and: | ||
FiredEvents events = FiredEvents.beginStoringFiredEventsOf(stage); | ||
moveBy(1, 0); | ||
events.stopStoringFiredEvents(); | ||
|
||
// when: | ||
AssertionError error = getThrownErrorPostMapper(showFiredEvents(events, TAB)); | ||
|
||
// then: | ||
assertThat(error.getMessage(), hasAddedTextThatContains("MouseEvent")); | ||
assertThat(error.getMessage(), hasAddedTextNotContaining("ScrollEvent")); | ||
} | ||
|
||
private AssertionError getThrownErrorPostMapper(Function<StringBuilder, StringBuilder> errorMessageMapper) { | ||
try { | ||
FxAssert.verifyThat(false, alwaysFail(), errorMessageMapper); | ||
throw new AssertionError("Error: verifyThat did not throw an error when it should have."); | ||
} | ||
catch (AssertionError error) { | ||
return error; | ||
} | ||
} | ||
|
||
private Matcher<Object> alwaysFail() { | ||
return new AlwaysFailsMatcher(); | ||
} | ||
|
||
private Matcher<String> hasAddedTextEqualTo(String addedText) { | ||
return new RemoveBlankMessageMatcher(addedText) { | ||
@Override | ||
public boolean matches(Object object) { | ||
return addedText.equals(replaceBlankPart(object)); | ||
} | ||
}; | ||
} | ||
|
||
private Matcher<String> hasAddedTextThatContains(String text) { | ||
return new RemoveBlankMessageMatcher( | ||
text, | ||
addedText -> "Added text: '" + addedText + "' does not contain '" + text + "'" | ||
) { | ||
|
||
@Override | ||
public boolean matches(Object item) { | ||
return replaceBlankPart(item).contains(text); | ||
} | ||
}; | ||
} | ||
|
||
private Matcher<String> hasAddedTextNotContaining(String text) { | ||
return new RemoveBlankMessageMatcher( | ||
text, | ||
addedText -> "Added text: '" + addedText + "' contains '" + text + "'" | ||
) { | ||
|
||
@Override | ||
public boolean matches(Object item) { | ||
return !replaceBlankPart(item).contains(text); | ||
} | ||
}; | ||
} | ||
|
||
private abstract class RemoveBlankMessageMatcher extends BaseMatcher<String> { | ||
|
||
private final String toDescribe; | ||
private final UnaryOperator<String> mismatchDescribe; | ||
|
||
public RemoveBlankMessageMatcher(String toDescribe) { | ||
this(toDescribe, UnaryOperator.identity()); | ||
} | ||
|
||
public RemoveBlankMessageMatcher(String toDescribe, UnaryOperator<String> mismatchDescribe) { | ||
super(); | ||
this.toDescribe = toDescribe; | ||
this.mismatchDescribe = mismatchDescribe; | ||
} | ||
|
||
@Override | ||
public void describeTo(Description description) { | ||
description | ||
.appendText(">>>") | ||
.appendText(toDescribe.replace("\n", "\\n")) | ||
.appendText("<<<"); | ||
} | ||
|
||
@Override | ||
public void describeMismatch(Object object, | ||
Description description) { | ||
description | ||
.appendText("-->") | ||
.appendValue(mismatchDescribe.apply( | ||
replaceBlankPart(object)) | ||
) | ||
.appendText("<--"); | ||
} | ||
|
||
protected String replaceBlankPart(Object object) { | ||
return ((String) object).replace(AlwaysFailsMatcher.BLANK_MESSAGE, ""); | ||
} | ||
} | ||
|
||
private class AlwaysFailsMatcher extends BaseMatcher<Object> { | ||
|
||
public static final String BLANK_MESSAGE = "\nExpected: \n but: "; | ||
|
||
public AlwaysFailsMatcher() { | ||
super(); | ||
} | ||
|
||
@Override | ||
public void describeTo(Description description) { | ||
// do nothing | ||
} | ||
|
||
@Override | ||
@SuppressWarnings("unchecked") | ||
public boolean matches(Object object) { | ||
return false; | ||
} | ||
|
||
@Override | ||
public void describeMismatch(Object object, | ||
Description description) { | ||
// do nothing | ||
} | ||
}; | ||
|
||
} |