Add test templates
This commit is contained in:
parent
38ea6a91fe
commit
94e81e5e08
@ -3,15 +3,33 @@
|
||||
# and
|
||||
# https://gitlab.stud.idi.ntnu.no/tdt4140-staff/examples/-/blob/master/.gitlab-ci.yml
|
||||
|
||||
image: maven:3.6.3-openjdk-15
|
||||
image: maven:3-openjdk-15-slim
|
||||
|
||||
variables:
|
||||
|
||||
# This will suppress any download for dependencies and plugins or upload messages which would clutter the console log.
|
||||
# `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work.
|
||||
MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
|
||||
MAVEN_OPTS: " \
|
||||
-Dhttps.protocols=TLSv1.2 \
|
||||
-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository \
|
||||
-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN \
|
||||
-Dorg.slf4j.simpleLogger.showDateTime=true \
|
||||
-Djava.awt.headless=true"
|
||||
|
||||
# As of Maven 3.3.0 instead of this you may define these options in `.mvn/maven.config` so the same config is used
|
||||
# when running from the command line.
|
||||
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version"
|
||||
MAVEN_CLI_OPTS: " \
|
||||
--batch-mode \
|
||||
--errors \
|
||||
--fail-at-end \
|
||||
--show-version \
|
||||
-Dprism.verbose=true \
|
||||
-Dtestfx.robot=glass \
|
||||
-Dtestfx.headless=true \
|
||||
-Dglass.platform=Monocle \
|
||||
-Dprism.order=sw \
|
||||
-Dprism.text=t2k \
|
||||
-Dtestfx.setup.timeout=60000"
|
||||
|
||||
# Cache downloaded dependencies and plugins between builds.
|
||||
# To keep cache across branches add 'key: "$CI_JOB_NAME"'
|
||||
@ -38,6 +56,8 @@ unittest:
|
||||
stage: test
|
||||
needs: [build]
|
||||
script:
|
||||
- "apt update"
|
||||
- "apt install -y openjfx"
|
||||
- "mvn package $MAVEN_CLI_OPTS"
|
||||
artifacts:
|
||||
paths:
|
||||
@ -46,12 +66,15 @@ unittest:
|
||||
reports:
|
||||
junit:
|
||||
- target/surefire-reports/TEST-*.xml
|
||||
- target/failsafe-reports/TEST-*.xml
|
||||
# TODO: Separate unit tests and integration tests
|
||||
# - target/failsafe-reports/TEST-*.xml
|
||||
|
||||
generate-coverage:
|
||||
stage: docs
|
||||
script:
|
||||
- 'mvn clean jacoco:prepare-agent test jacoco:report'
|
||||
- "apt update"
|
||||
- "apt install -y openjfx"
|
||||
- 'mvn clean jacoco:prepare-agent test $MAVEN_CLI_OPTS jacoco:report'
|
||||
- 'cat target/site/jacoco/index.html'
|
||||
coverage: '/Total.*?([0-9]{1,3})%/'
|
||||
artifacts:
|
||||
|
32
pom.xml
32
pom.xml
@ -42,7 +42,6 @@
|
||||
<version>3.2.0-01</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- JUnit 5 -->
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
@ -65,6 +64,36 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Hamcrest - Matchers to help testing the JavaFX UI -->
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest</artifactId>
|
||||
<version>2.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Monocle - Headless UI testing in CI -->
|
||||
<dependency>
|
||||
<groupId>org.testfx</groupId>
|
||||
<artifactId>openjfx-monocle</artifactId>
|
||||
<version>jdk-12.0.1+2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Mockito - Mocking Library for performing isolated unit tests -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-inline</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-junit-jupiter</artifactId>
|
||||
<version>2.23.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- JavaDoc -->
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@ -133,7 +162,6 @@
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
@ -35,6 +35,7 @@ public class Main extends Application {
|
||||
*/
|
||||
private void setupWindow(Stage window) {
|
||||
window.setTitle(TITLE);
|
||||
if (window.getIcons().isEmpty())
|
||||
window.getIcons().add(new Image(getClass().getResourceAsStream(ICON_PATH)));
|
||||
}
|
||||
|
||||
@ -53,6 +54,7 @@ public class Main extends Application {
|
||||
*/
|
||||
private void createScene() {
|
||||
this.scene = new Scene(fxmlRoot);
|
||||
this.scene.setUserData(this.fxmlLoader);
|
||||
Model.setScene(scene);
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,16 @@ public class MainController implements Initializable {
|
||||
return hostServices;
|
||||
}
|
||||
|
||||
//TODO: Document
|
||||
public List<Controller> getInnerControllers() {
|
||||
return List.of(
|
||||
editorController,
|
||||
filetreeController,
|
||||
modelineController,
|
||||
menubarController
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a reference to the global Host Services API
|
||||
*
|
||||
|
@ -66,6 +66,11 @@ public class EditorController implements Initializable, Controller, FileManageme
|
||||
this.eventBus.register(this);
|
||||
}
|
||||
|
||||
// TODO: document
|
||||
public CodeArea getEditor() {
|
||||
return editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies highlighting to the editor.
|
||||
*
|
||||
@ -146,21 +151,20 @@ public class EditorController implements Initializable, Controller, FileManageme
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public void setEditorContent(String filePath) {
|
||||
if (filePath == null) {
|
||||
editor.clear();
|
||||
editor.appendText("// New File");
|
||||
return;
|
||||
}
|
||||
// if (filePath == null) {
|
||||
// editor.clear();
|
||||
// editor.appendText("// New File");
|
||||
// return;
|
||||
// }
|
||||
try (Scanner sc = new Scanner(new File(filePath))) {
|
||||
if (filePath.endsWith(".java") || filePath.endsWith(".md")) {
|
||||
// if (filePath.endsWith(".java") || filePath.endsWith(".md")) {
|
||||
editor.clear();
|
||||
while (sc.hasNextLine()) {
|
||||
editor.appendText(sc.nextLine());
|
||||
editor.appendText("\n");
|
||||
}
|
||||
} else {
|
||||
throw new FileNotFoundException();
|
||||
editor.appendText(sc.nextLine() + "\n");
|
||||
}
|
||||
// } else {
|
||||
// throw new FileNotFoundException();
|
||||
// }
|
||||
|
||||
} catch (FileNotFoundException ex) {
|
||||
Alert error = new Alert(AlertType.ERROR);
|
||||
@ -208,7 +212,7 @@ public class EditorController implements Initializable, Controller, FileManageme
|
||||
* Updates Code Area (read from file) whenever the FileSelected is changed
|
||||
*/
|
||||
@Subscribe
|
||||
private void handle(FileSelectedEvent event) {
|
||||
public void handle(FileSelectedEvent event) {
|
||||
this.setEditorContent(event.getPath());
|
||||
}
|
||||
|
||||
@ -226,7 +230,7 @@ public class EditorController implements Initializable, Controller, FileManageme
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void handle(ToggleCommentEvent event) {
|
||||
public void handle(ToggleCommentEvent event) {
|
||||
this.toggleComment();
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@ -124,12 +125,26 @@ public class FiletreeController implements Initializable, Controller {
|
||||
String name = file.getName();
|
||||
String ext = (name.substring(file.getName().lastIndexOf(".") + 1, file.getName().length()));
|
||||
|
||||
if ("java".equals(ext))
|
||||
createExtension(name, java, parent);
|
||||
else if ("md".equals(ext))
|
||||
createExtension(name, md, parent);
|
||||
else
|
||||
createExtension(name, placeholder, parent);
|
||||
try {
|
||||
createExtension(name, getIconForFile(file), parent);
|
||||
} catch (Exception e) {
|
||||
System.err.println("ICON NOT FOUND: " + file.getPath());
|
||||
}
|
||||
|
||||
// if ("java".equals(ext))
|
||||
// createExtension(name, java, parent);
|
||||
// else if ("md".equals(ext))
|
||||
// createExtension(name, md, parent);
|
||||
// else
|
||||
// createExtension(name, placeholder, parent);
|
||||
}
|
||||
|
||||
private Image getIconForFile(File file) throws IOException {
|
||||
String mimeType = Files.probeContentType(file.toPath()).replace('/', '-');
|
||||
String iconPath = (mimeType != null)
|
||||
? "/graphics/filetreeicons/" + mimeType + ".png"
|
||||
: "/graphics/filetreeicons/file.png";
|
||||
return new Image(getClass().getResourceAsStream(iconPath));
|
||||
}
|
||||
|
||||
private void createExtension(String name, Image image, CheckBoxTreeItem<String> parent) {
|
||||
|
@ -3,4 +3,4 @@ package app.events;
|
||||
/**
|
||||
* Base class for any type of event of the eventbus
|
||||
*/
|
||||
abstract class Event {}
|
||||
public abstract class Event {}
|
||||
|
@ -13,7 +13,7 @@ import app.model.ProgrammingLanguage;
|
||||
* Common static operations that can be executed on any class
|
||||
* that implements {@link app.model.ProgrammingLanguage ProgrammingLanguage}
|
||||
*/
|
||||
public class LanguageOperations {
|
||||
public final class LanguageOperations {
|
||||
|
||||
/**
|
||||
* Use a matcher to find the styleclass of the next match
|
||||
|
@ -10,7 +10,8 @@
|
||||
prefHeight="400"
|
||||
xmlns="http://javafx.com/javafx/8.0.65"
|
||||
xmlns:fx="http://javafx.com/fxml/1"
|
||||
fx:controller="app.MainController">
|
||||
fx:controller="app.MainController"
|
||||
fx:id="root">
|
||||
|
||||
<top>
|
||||
<!-- Menubar -->
|
||||
|
44
src/test/java/app/FxTestTemplate.java
Normal file
44
src/test/java/app/FxTestTemplate.java
Normal file
@ -0,0 +1,44 @@
|
||||
package app;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.stage.Stage;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.testfx.api.FxToolkit;
|
||||
import org.testfx.framework.junit5.ApplicationTest;
|
||||
import org.testfx.util.WaitForAsyncUtils;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class FxTestTemplate extends ApplicationTest {
|
||||
|
||||
private Stage stage;
|
||||
|
||||
@BeforeEach
|
||||
public void runAppToTests() throws Exception {
|
||||
FxToolkit.registerPrimaryStage();
|
||||
FxToolkit.setupApplication(Main::new);
|
||||
FxToolkit.showStage();
|
||||
WaitForAsyncUtils.waitForFxEvents(100);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void stopApp() throws TimeoutException {
|
||||
FxToolkit.cleanupStages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage){
|
||||
this.stage = primaryStage;
|
||||
primaryStage.toFront();
|
||||
}
|
||||
|
||||
public Stage getStage() {
|
||||
return stage;
|
||||
}
|
||||
|
||||
public <T extends Node> T find(final String query) {
|
||||
/** TestFX provides many operations to retrieve elements from the loaded GUI. */
|
||||
return lookup(query).query();
|
||||
}
|
||||
}
|
@ -1,16 +1,74 @@
|
||||
package app;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.platform.commons.annotation.Testable;
|
||||
|
||||
public class MainTest {
|
||||
import app.controllers.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javafx.scene.layout.BorderPane;
|
||||
|
||||
import app.testing.FxTestTemplate;
|
||||
|
||||
|
||||
@Testable
|
||||
public class MainTest extends FxTestTemplate {
|
||||
|
||||
@Test
|
||||
@DisplayName("Temp Test")
|
||||
public void tempTest() {
|
||||
assertEquals(1, 1);
|
||||
@DisplayName("Check that the stage title is correct")
|
||||
public void should_have_stage_title() {
|
||||
assertEquals("Banana Editor", this.getStage().getTitle());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
@DisplayName("Check that the stage has an icon")
|
||||
public void should_have_stage_icon() {
|
||||
assertEquals(1, this.getStage().getIcons().size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
@DisplayName("Check that the root element is present")
|
||||
public void should_have_root() {
|
||||
BorderPane app = (BorderPane) find("#root");
|
||||
assertNotNull(app);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
@DisplayName("Check that all subcontrollers are present")
|
||||
public void should_have_subcontrollers() {
|
||||
this
|
||||
.getMainController()
|
||||
.getInnerControllers()
|
||||
.forEach((Controller controller) -> assertNotNull(controller));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Check that the scene is correct")
|
||||
public void should_have_scene() throws IOException {
|
||||
assertNotNull(this.getStage().getScene());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Check that the CSS is set")
|
||||
public void should_have_css() {
|
||||
List<String> expectedCSS =
|
||||
List.of("/styling/themes/monokai.css", "/styling/languages/java.css")
|
||||
.stream()
|
||||
.map(p -> getClass().getResource(p).toExternalForm())
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(expectedCSS, this.getStage().getScene().getStylesheets());
|
||||
}
|
||||
}
|
238
src/test/java/app/controllers/EditorControllerTest.java
Normal file
238
src/test/java/app/controllers/EditorControllerTest.java
Normal file
@ -0,0 +1,238 @@
|
||||
package app.controllers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.fxmisc.richtext.CodeArea;
|
||||
import org.fxmisc.richtext.model.StyleSpans;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import app.testing.FxTestTemplate;
|
||||
import app.model.Model;
|
||||
import app.model.ProgrammingLanguage;
|
||||
import app.service.LanguageOperations;
|
||||
import app.events.CopyEvent;
|
||||
import app.events.CutEvent;
|
||||
import app.events.FileSelectedEvent;
|
||||
import app.events.LanguageChangedEvent;
|
||||
import app.events.PasteEvent;
|
||||
import app.events.RedoEvent;
|
||||
import app.events.ToggleCommentEvent;
|
||||
import app.events.ToggleWrapTextEvent;
|
||||
import app.events.UndoEvent;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class EditorControllerTest extends FxTestTemplate {
|
||||
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<String> captor;
|
||||
|
||||
@Mock
|
||||
private CodeArea editor;
|
||||
|
||||
private EventBus eventBus;
|
||||
|
||||
@InjectMocks
|
||||
private EditorController controller;
|
||||
|
||||
private String mockContent = """
|
||||
class HelloWorld {
|
||||
private String message = "Hello world";
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
private String mockLine = "private String message = \"Hello world\";";
|
||||
|
||||
@BeforeEach
|
||||
public void insertEventBus() {
|
||||
this.eventBus = new EventBus();
|
||||
this.controller.setEventBus(eventBus);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test handling of FileSelectedEvent with a real file")
|
||||
public void testFileSelectedEventWithRealFile() throws IOException {
|
||||
|
||||
String resourcePath = "/testfile.txt";
|
||||
String filePath = getClass().getResource(resourcePath).getPath();
|
||||
File file = new File(filePath);
|
||||
List<String> content =
|
||||
Files.readAllLines(file.toPath())
|
||||
.stream()
|
||||
.map(s -> s + "\n")
|
||||
.collect(Collectors.toList());
|
||||
|
||||
eventBus.post(new FileSelectedEvent(filePath));
|
||||
verify(editor, times(content.size())).appendText(captor.capture());
|
||||
|
||||
assertEquals(content, captor.getAllValues());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test handling of FileSelectedEvent with a file that doesn't exist")
|
||||
public void testFileSelectedEventWithUnrealFile() throws IOException {
|
||||
|
||||
String brokenFilePath = "/doesNotExist.txt";
|
||||
eventBus.post(new FileSelectedEvent(brokenFilePath));
|
||||
|
||||
verify(editor, never()).clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test handling of LanguageChangedEvent")
|
||||
public void testLanguageChangedEvent(){
|
||||
|
||||
when(editor.getText()).thenReturn(mockContent);
|
||||
|
||||
try (MockedStatic<LanguageOperations> mocked = mockStatic(LanguageOperations.class)) {
|
||||
mocked.when(() -> LanguageOperations.syntaxHighlight(anyString(), any()))
|
||||
.thenReturn(StyleSpans.singleton(null, 0));
|
||||
|
||||
eventBus.post(new LanguageChangedEvent("markdown"));
|
||||
mocked.verify(() -> LanguageOperations.syntaxHighlight(anyString(), any()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test handling of ToggleCommentEvent when not selected")
|
||||
public void testToggleCommentEventNotSelect(){
|
||||
|
||||
ProgrammingLanguage lang = mock(ProgrammingLanguage.class);
|
||||
when(editor.getSelectedText()).thenReturn("");
|
||||
when(editor.getText(anyInt())).thenReturn(mockLine);
|
||||
|
||||
try (MockedStatic<Model> mocked = mockStatic(Model.class)) {
|
||||
mocked.when(() -> Model.getLanguage()).thenReturn(lang);
|
||||
|
||||
when(lang.isCommentedLine(anyString())).thenReturn(false);
|
||||
eventBus.post(new ToggleCommentEvent());
|
||||
verify(lang).commentLine(anyString());
|
||||
|
||||
when(lang.isCommentedLine(anyString())).thenReturn(true);
|
||||
eventBus.post(new ToggleCommentEvent());
|
||||
verify(lang).unCommentLine(anyString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test handling of ToggleCommentEvent when selected")
|
||||
public void testToggleCommentEventSelect(){
|
||||
|
||||
ProgrammingLanguage lang = mock(ProgrammingLanguage.class);
|
||||
when(editor.getSelectedText()).thenReturn("Selected Text");
|
||||
|
||||
try (MockedStatic<Model> mocked = mockStatic(Model.class)) {
|
||||
mocked.when(() -> Model.getLanguage()).thenReturn(lang);
|
||||
|
||||
when(lang.isCommentedSelection(anyString())).thenReturn(false);
|
||||
eventBus.post(new ToggleCommentEvent());
|
||||
verify(lang).commentSelection(anyString());
|
||||
|
||||
when(lang.isCommentedSelection(anyString())).thenReturn(true);
|
||||
eventBus.post(new ToggleCommentEvent());
|
||||
verify(lang).unCommentSelection(anyString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test handling of ToggleWrapTextEvent")
|
||||
public void testToggleWrapTextEvent(){
|
||||
eventBus.post(new ToggleWrapTextEvent(true));
|
||||
verify(editor).setWrapText(true);
|
||||
eventBus.post(new ToggleWrapTextEvent(false));
|
||||
verify(editor).setWrapText(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test handling of UndoEvent")
|
||||
public void testUndoEvent(){
|
||||
when(editor.isFocused()).thenReturn(true);
|
||||
eventBus.post(new UndoEvent());
|
||||
verify(editor, times(1)).undo();
|
||||
|
||||
when(editor.isFocused()).thenReturn(false);
|
||||
eventBus.post(new UndoEvent());
|
||||
// Should not have been called one more time
|
||||
verify(editor, times(1)).undo();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test handling of RedoEvent")
|
||||
public void testRedoEvent(){
|
||||
when(editor.isFocused()).thenReturn(true);
|
||||
eventBus.post(new RedoEvent());
|
||||
verify(editor, times(1)).redo();
|
||||
|
||||
when(editor.isFocused()).thenReturn(false);
|
||||
eventBus.post(new RedoEvent());
|
||||
verify(editor, times(1)).redo();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test handling of CopyEvent")
|
||||
public void testCopyEvent(){
|
||||
when(editor.isFocused()).thenReturn(true);
|
||||
eventBus.post(new CopyEvent());
|
||||
verify(editor, times(1)).copy();
|
||||
|
||||
when(editor.isFocused()).thenReturn(false);
|
||||
eventBus.post(new CopyEvent());
|
||||
verify(editor, times(1)).copy();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test handling of CutEvent")
|
||||
public void testCutEvent(){
|
||||
when(editor.isFocused()).thenReturn(true);
|
||||
eventBus.post(new CutEvent());
|
||||
verify(editor, times(1)).cut();
|
||||
|
||||
when(editor.isFocused()).thenReturn(false);
|
||||
eventBus.post(new CutEvent());
|
||||
verify(editor, times(1)).cut();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test handling of PasteEvent")
|
||||
public void testPasteEvent(){
|
||||
when(editor.isFocused()).thenReturn(true);
|
||||
eventBus.post(new PasteEvent());
|
||||
verify(editor, times(1)).paste();
|
||||
|
||||
when(editor.isFocused()).thenReturn(false);
|
||||
eventBus.post(new PasteEvent());
|
||||
verify(editor, times(1)).paste();
|
||||
}
|
||||
}
|
18
src/test/java/app/events/FileSaveStateChangedEventTest.java
Normal file
18
src/test/java/app/events/FileSaveStateChangedEventTest.java
Normal file
@ -0,0 +1,18 @@
|
||||
package app.events;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import app.model.Model;
|
||||
import app.testing.EventTestTemplate;
|
||||
|
||||
public class FileSaveStateChangedEventTest extends EventTestTemplate {
|
||||
|
||||
@Test
|
||||
@DisplayName("Check that model gets changed on constructor")
|
||||
public void checkModel() {
|
||||
new FileSaveStateChangedEvent(true);
|
||||
this.mockModel.verify(() -> Model.setFileIsSaved(true));
|
||||
}
|
||||
|
||||
}
|
5
src/test/java/app/testing/ControllerTestTemplate.java
Normal file
5
src/test/java/app/testing/ControllerTestTemplate.java
Normal file
@ -0,0 +1,5 @@
|
||||
package app.testing;
|
||||
|
||||
public class ControllerTestTemplate extends FxTestTemplate {
|
||||
|
||||
}
|
25
src/test/java/app/testing/EventTestTemplate.java
Normal file
25
src/test/java/app/testing/EventTestTemplate.java
Normal file
@ -0,0 +1,25 @@
|
||||
package app.testing;
|
||||
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import app.model.Model;
|
||||
|
||||
public class EventTestTemplate extends FxTestTemplate {
|
||||
|
||||
public MockedStatic<Model> mockModel;
|
||||
|
||||
@BeforeEach
|
||||
public void openModel() {
|
||||
mockModel = mockStatic(Model.class);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void closeModel() {
|
||||
mockModel.close();
|
||||
}
|
||||
|
||||
}
|
56
src/test/java/app/testing/FxTestTemplate.java
Normal file
56
src/test/java/app/testing/FxTestTemplate.java
Normal file
@ -0,0 +1,56 @@
|
||||
package app.testing;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Node;
|
||||
import javafx.stage.Stage;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.testfx.api.FxToolkit;
|
||||
import org.testfx.framework.junit5.ApplicationTest;
|
||||
import org.testfx.util.WaitForAsyncUtils;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import app.Main;
|
||||
import app.MainController;
|
||||
|
||||
public class FxTestTemplate extends ApplicationTest {
|
||||
|
||||
private Stage stage;
|
||||
private Application application;
|
||||
|
||||
@BeforeEach
|
||||
public void runAppToTests() throws Exception {
|
||||
FxToolkit.registerPrimaryStage();
|
||||
this.application = FxToolkit.setupApplication(Main::new);
|
||||
|
||||
FxToolkit.showStage();
|
||||
WaitForAsyncUtils.waitForFxEvents(100);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void stopApp() throws TimeoutException {
|
||||
FxToolkit.cleanupStages();
|
||||
FxToolkit.cleanupApplication(this.application);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage){
|
||||
this.stage = primaryStage;
|
||||
primaryStage.toFront();
|
||||
}
|
||||
|
||||
public Stage getStage() {
|
||||
return stage;
|
||||
}
|
||||
|
||||
public MainController getMainController() {
|
||||
return ((FXMLLoader) this.stage.getScene().getUserData()).getController();
|
||||
}
|
||||
|
||||
public <T extends Node> T find(final String query) {
|
||||
/** TestFX provides many operations to retrieve elements from the loaded GUI. */
|
||||
return lookup(query).query();
|
||||
}
|
||||
}
|
3
src/test/resources/testfile.txt
Normal file
3
src/test/resources/testfile.txt
Normal file
@ -0,0 +1,3 @@
|
||||
public class testfile {
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user