Skip to content

Commit

Permalink
(test) Add tests for DebugUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
JordanMartinez committed Aug 24, 2017
1 parent 301905f commit ae50160
Showing 1 changed file with 296 additions and 0 deletions.
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
}
};

}

0 comments on commit ae50160

Please sign in to comment.