diff --git a/.github/workflows/ant.yml b/.github/workflows/ant.yml deleted file mode 100644 index 1a1ec4164..000000000 --- a/.github/workflows/ant.yml +++ /dev/null @@ -1,39 +0,0 @@ -# This workflow will build a Java project with Ant -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-ant - -name: Java CI - -on: - push: - branches: [ javaUI ] - pull_request: - branches: [ javaUI ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6 - - name: Install dependencies - run: sudo apt update && sudo apt install gettext po4a - - name: Set up JDK 11 - uses: actions/setup-java@v2 - with: - java-version: '11' - distribution: 'adopt' - - name: Test exercise solutions (Ant) - run: ant -noinput -buildfile build.xml test-exos - - name: Unit tests (Ant) - run: ant -noinput -buildfile build.xml test-unit - - name: Integration tests (Ant) - run: ant -noinput -buildfile build.xml test-integration - - name: Update translations with po4a - run: po4a po4a.conf - - name: Build jarfile (Ant) - run: ant -noinput -buildfile build.xml dist - - name: Upload jar - uses: actions/upload-artifact@v4 - with: - path: dist/*.jar diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 000000000..d6e243c7e --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,67 @@ +# This workflow builds PLM with Maven and runs its test suite. +# See https://docs.github.com/actions/automating-builds-and-tests/building-and-testing-java-with-maven +name: Java CI + +on: + push: + branches: [ javaUI ] + pull_request: + branches: [ javaUI ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Install gettext (needed by the i18n message-bundle generation) + run: sudo apt-get update && sudo apt-get install -y gettext + # Scala 2.12's compiler bridge does not run on JDK 22+, and maven.compiler.release is 17. + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + java-version: '21' + distribution: 'temurin' + cache: maven + - name: Build the self-contained jar with Maven + run: mvn -B -DskipTests package + - name: Upload jar + uses: actions/upload-artifact@v6 + with: + path: target/*.jar + + test: + name: test (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + steps: + - uses: actions/checkout@v6 + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + java-version: '21' + distribution: 'temurin' + cache: maven + # The i18n message-bundle generation needs gettext (msgfmt) on PATH. + - name: Install gettext + xvfb (Linux) + if: runner.os == 'Linux' + run: sudo apt-get update && sudo apt-get install -y gettext xvfb + - name: Install gettext (macOS) + if: runner.os == 'macOS' + run: | + brew install gettext + echo "$(brew --prefix gettext)/bin" >> "$GITHUB_PATH" + - name: Install gettext (Windows) + if: runner.os == 'Windows' + run: choco install gettext --yes --no-progress + # Linux runners are headless -> run the Swing tests under a virtual display. + # Windows and macOS runners have a real display, so run them directly. + - name: Run tests (Linux, under xvfb) + if: runner.os == 'Linux' + run: xvfb-run -a mvn -B test + - name: Run tests (Windows / macOS) + if: runner.os != 'Linux' + run: mvn -B test diff --git a/.gitignore b/.gitignore index 411567a8a..bfd075cc4 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,5 @@ lib/plm-messages.jar nbproject/ manifest.mf build/ +# Maven build output +target/ diff --git a/lib/RSyntaxTextArea-2.5.4.jar b/lib/RSyntaxTextArea-2.5.4.jar deleted file mode 100644 index 2b9ed5641..000000000 Binary files a/lib/RSyntaxTextArea-2.5.4.jar and /dev/null differ diff --git a/lib/appbundler-1.0.jar b/lib/appbundler-1.0.jar deleted file mode 100644 index ef30f1cb4..000000000 Binary files a/lib/appbundler-1.0.jar and /dev/null differ diff --git a/lib/commons-logging-1.1.1.jar b/lib/commons-logging-1.1.1.jar deleted file mode 100644 index 1deef144c..000000000 Binary files a/lib/commons-logging-1.1.1.jar and /dev/null differ diff --git a/lib/gettext-commons-0.9.6.jar b/lib/gettext-commons-0.9.6.jar deleted file mode 100644 index 115ae64a7..000000000 Binary files a/lib/gettext-commons-0.9.6.jar and /dev/null differ diff --git a/lib/gson-2.2.4.jar b/lib/gson-2.2.4.jar deleted file mode 100644 index 9478253e8..000000000 Binary files a/lib/gson-2.2.4.jar and /dev/null differ diff --git a/lib/guava-19.0.jar b/lib/guava-19.0.jar deleted file mode 100644 index bac23684c..000000000 Binary files a/lib/guava-19.0.jar and /dev/null differ diff --git a/lib/hamcrest-core-1.3.jar b/lib/hamcrest-core-1.3.jar deleted file mode 100644 index 9d5fe16e3..000000000 Binary files a/lib/hamcrest-core-1.3.jar and /dev/null differ diff --git a/lib/httpclient-4.3.4.jar b/lib/httpclient-4.3.4.jar deleted file mode 100644 index 6cc67f0bf..000000000 Binary files a/lib/httpclient-4.3.4.jar and /dev/null differ diff --git a/lib/httpcore-4.3.2.jar b/lib/httpcore-4.3.2.jar deleted file mode 100644 index 766a6681f..000000000 Binary files a/lib/httpcore-4.3.2.jar and /dev/null differ diff --git a/lib/httpmime-4.3.4.jar b/lib/httpmime-4.3.4.jar deleted file mode 100644 index effa8be72..000000000 Binary files a/lib/httpmime-4.3.4.jar and /dev/null differ diff --git a/lib/jline2-2.14.6.jar b/lib/jline2-2.14.6.jar deleted file mode 100644 index 9f842a512..000000000 Binary files a/lib/jline2-2.14.6.jar and /dev/null differ diff --git a/lib/jnr-constants-0.9.9.jar b/lib/jnr-constants-0.9.9.jar deleted file mode 100644 index 9feba12eb..000000000 Binary files a/lib/jnr-constants-0.9.9.jar and /dev/null differ diff --git a/lib/jnr-ffi-2.1.7.jar b/lib/jnr-ffi-2.1.7.jar deleted file mode 100644 index 354888c58..000000000 Binary files a/lib/jnr-ffi-2.1.7.jar and /dev/null differ diff --git a/lib/jnr-posix-3.0.45.jar b/lib/jnr-posix-3.0.45.jar deleted file mode 100644 index 7c57dd72e..000000000 Binary files a/lib/jnr-posix-3.0.45.jar and /dev/null differ diff --git a/lib/jruby-1.5.6-5.jar b/lib/jruby-1.5.6-5.jar deleted file mode 100644 index 84e694987..000000000 Binary files a/lib/jruby-1.5.6-5.jar and /dev/null differ diff --git a/lib/jsch-0.1.50.jar b/lib/jsch-0.1.50.jar deleted file mode 100644 index 85c044f21..000000000 Binary files a/lib/jsch-0.1.50.jar and /dev/null differ diff --git a/lib/json_simple-1.1.jar b/lib/json_simple-1.1.jar deleted file mode 100644 index 81357117d..000000000 Binary files a/lib/json_simple-1.1.jar and /dev/null differ diff --git a/lib/junit-4.11.jar b/lib/junit-4.11.jar deleted file mode 100644 index aaf744484..000000000 Binary files a/lib/junit-4.11.jar and /dev/null differ diff --git a/lib/jython/antlr3-runtime-3.2.jar b/lib/jython/antlr3-runtime-3.2.jar deleted file mode 100644 index f29c2c5ea..000000000 Binary files a/lib/jython/antlr3-runtime-3.2.jar and /dev/null differ diff --git a/lib/jython/asm-7.2.jar b/lib/jython/asm-7.2.jar deleted file mode 100644 index e9cb96393..000000000 Binary files a/lib/jython/asm-7.2.jar and /dev/null differ diff --git a/lib/jython/jython-2.7.2~rc1.jar b/lib/jython/jython-2.7.2~rc1.jar deleted file mode 100644 index dbbfb0d5a..000000000 Binary files a/lib/jython/jython-2.7.2~rc1.jar and /dev/null differ diff --git a/lib/miglayout-4.2.jar b/lib/miglayout-4.2.jar deleted file mode 100644 index 24b8d6cfb..000000000 Binary files a/lib/miglayout-4.2.jar and /dev/null differ diff --git a/lib/mockito-all-1.9.5.jar b/lib/mockito-all-1.9.5.jar deleted file mode 100644 index 00416eb38..000000000 Binary files a/lib/mockito-all-1.9.5.jar and /dev/null differ diff --git a/lib/org.eclipse.egit.github.core-2.1.5.jar b/lib/org.eclipse.egit.github.core-2.1.5.jar deleted file mode 100644 index eba0cbf06..000000000 Binary files a/lib/org.eclipse.egit.github.core-2.1.5.jar and /dev/null differ diff --git a/lib/org.eclipse.jgit-3.2.0.201312181205-r.jar b/lib/org.eclipse.jgit-3.2.0.201312181205-r.jar deleted file mode 100644 index 172c4d4cd..000000000 Binary files a/lib/org.eclipse.jgit-3.2.0.201312181205-r.jar and /dev/null differ diff --git a/lib/scala/jna-5.3.1.jar b/lib/scala/jna-5.3.1.jar deleted file mode 100644 index d4a9471be..000000000 Binary files a/lib/scala/jna-5.3.1.jar and /dev/null differ diff --git a/lib/scala/scala-compiler-2.11.12.jar b/lib/scala/scala-compiler-2.11.12.jar deleted file mode 100644 index d0f3f74c4..000000000 Binary files a/lib/scala/scala-compiler-2.11.12.jar and /dev/null differ diff --git a/lib/scala/scala-library-2.11.12.jar b/lib/scala/scala-library-2.11.12.jar deleted file mode 100644 index f2afb11a9..000000000 Binary files a/lib/scala/scala-library-2.11.12.jar and /dev/null differ diff --git a/lib/scala/scala-reflect-2.11.12.jar b/lib/scala/scala-reflect-2.11.12.jar deleted file mode 100644 index 51f5a5ee6..000000000 Binary files a/lib/scala/scala-reflect-2.11.12.jar and /dev/null differ diff --git a/lib/tools-openjdk8.jar b/lib/tools-openjdk8.jar deleted file mode 100644 index 8899f9ee4..000000000 Binary files a/lib/tools-openjdk8.jar and /dev/null differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 000000000..133045dfe --- /dev/null +++ b/pom.xml @@ -0,0 +1,429 @@ + + + 4.0.0 + + org.plm + plm + 2.9.3-SNAPSHOT + jar + + Programmer's Learning Machine + + Maven build for PLM. Replaces the legacy ant build (build.xml) and its + hand-vendored lib/*.jar binaries. Dependencies are declared here and + fetched from Maven Central; the project is compiled jointly (Java + Scala) + from the existing src/ tree, and `mvn package` produces a self-contained + shaded uber-jar runnable as plm.core.ui.ProgrammersLearningMachine. + + + + UTF-8 + 17 + 2.12.20 + 2.12 + plm.core.ui.ProgrammersLearningMachine + + + + + + + org.scala-lang + scala-library + ${scala.version} + + + org.scala-lang + scala-reflect + ${scala.version} + + + org.scala-lang + scala-compiler + ${scala.version} + + + + + com.fifesoft + rsyntaxtextarea + 2.5.4 + + + com.miglayout + miglayout-swing + 4.2 + + + + + org.python + jython-standalone + 2.7.3 + + + + + org.jruby + jruby-complete + 9.4.8.0 + + + + + com.google.guava + guava + 33.2.1-jre + + + + jline + jline + 2.14.6 + + + + + org.apache.httpcomponents + httpclient + 4.5.14 + + + org.apache.httpcomponents + httpmime + 4.5.14 + + + commons-logging + commons-logging + 1.1.1 + + + + + com.googlecode.gettext-commons + gettext-commons + 0.9.8 + + + + + com.googlecode.json-simple + json-simple + 1.1.1 + + + junit + junit + + + + + com.google.code.gson + gson + 2.2.4 + + + + + org.eclipse.mylyn.github + org.eclipse.egit.github.core + 2.1.5 + + + + + org.eclipse.jgit + org.eclipse.jgit + 6.10.0.202406032230-r + + + + com.github.mwiede + jsch + 0.2.18 + + + + + junit + junit + 4.13.2 + provided + + + org.mockito + mockito-core + 4.11.0 + provided + + + + org.assertj + assertj-swing-junit + 3.17.1 + provided + + + + + + + + src + + **/*.py + **/*.c + **/*.js + **/*.scala + **/*.java + **/*.html + **/*.css + **/*.png + **/*.svg + **/*.map + + + + img + img + + **/*.png + **/*.svg + + + + lib/resources + resources + + + lib/doc + doc + + *.html + + + + ${project.basedir} + + ChangeLog + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.0 + + + add-source + generate-sources + + add-source + + + + src + + + + + + + + + net.alchim31.maven + scala-maven-plugin + 4.9.2 + + ${scala.version} + + -nobootcp + + + -Xss8m + + + + + scala-compile + process-resources + + add-source + compile + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + ${maven.compiler.release} + UTF-8 + + false + + -Xlint:none + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 3.1.0 + + + + com.googlecode.gettext-commons + gettext-commons + 0.9.8 + + + + + i18n-generate-bundles + process-classes + + run + + + + + + + + + + + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + false + false + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + module-info.class + + + + + + + ${main.class} + M. Quinson, G. Oster and others + + + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.5 + + + ${project.build.outputDirectory} + + **/git/GitSpyTest.java + **/git/GitUtilsTest.java + **/simple/test/JavaSimpleExerciseTest.java + **/gui/MainFrameSmokeTest.java + + -Djava.awt.headless=false + 600 + + false + + + + + diff --git a/src/lessons/welcome/methods/returning/ScalaMethodsReturningEntity.scala b/src/lessons/welcome/methods/returning/ScalaMethodsReturningEntity.scala index 2767eb7f5..cf93da225 100644 --- a/src/lessons/welcome/methods/returning/ScalaMethodsReturningEntity.scala +++ b/src/lessons/welcome/methods/returning/ScalaMethodsReturningEntity.scala @@ -1,6 +1,5 @@ package lessons.welcome.methods.returning; -import com.sun.org.apache.xpath.internal.operations.Bool import plm.core.model.Game diff --git a/src/plm/core/lang/LangScala.java b/src/plm/core/lang/LangScala.java index 55ec18b1e..7b7691b78 100644 --- a/src/plm/core/lang/LangScala.java +++ b/src/plm/core/lang/LangScala.java @@ -25,7 +25,12 @@ import scala.tools.nsc.Global.Run; import scala.tools.nsc.Settings; import scala.tools.nsc.interpreter.AbstractFileClassLoader; -import scala.tools.nsc.reporters.AbstractReporter; +// Scala 2.12 compiler API: scala.tools.nsc.reporters.AbstractReporter was +// removed. The reporter base is now scala.tools.nsc.reporters.Reporter, whose +// single abstract entry point is info0(pos, msg, Severity, force) and whose +// INFO/WARNING/ERROR severities are instance members (no longer string-named). +import scala.tools.nsc.reporters.Reporter; +import scala.reflect.internal.Reporter.Severity; public class LangScala extends JVMCompiledLang { @@ -156,57 +161,42 @@ public Class findClass(String className) { } } - class PLMReporter extends AbstractReporter { - final static int INFO = 0; - final static int WARNING = 1; - final static int ERROR = 2; - final int[] counts = new int[] {0, 0, 0}; + /* Ported from the Scala 2.11 reporter API (AbstractReporter, with + * display()/displayPrompt()/settings()/count() hooks) to the Scala 2.12 + * API: scala.tools.nsc.reporters.Reporter exposes a single abstract method, + * info0(Position, String, Severity, boolean force), + * and the INFO/WARNING/ERROR severities are instance members compared by + * identity (no more brittle toString() matching). The base class tracks + * error/warning state itself (hasErrors()), so we no longer keep our own + * counts[] array. The Settings are owned by the enclosing ScalaCompiler. */ + class PLMReporter extends Reporter { int offset=0; Vector messages = new Vector(); - Settings settings; public PLMReporter(Settings s) { - settings = s; + // Settings are no longer needed by the reporter base in 2.12. } public void setOffset(int _offset) { this.offset = _offset; } @Override - public Settings settings() { - return settings; - } - @Override - public void displayPrompt() { - /* Don't do that, pal. */ - } - private int severityRank(Severity s) { - String severityName = s.toString(); - int severity = -1; - if (severityName.equals("INFO") || severityName.equals("scala.tools.nsc.reporters.Reporter$Severity@0")) - severity = INFO; - if (severityName.equals("WARNING") || severityName.equals("scala.tools.nsc.reporters.Reporter$Severity@1")) - severity = WARNING; - if (severityName.equals("ERROR") || severityName.equals("scala.tools.nsc.reporters.Reporter$Severity@2")) - severity = ERROR; - if (severity == -1) - throw new RuntimeException("Got an unknown severity: "+severityName+". Please adapt the PLM to this new version of scala (or whatever)."); - return severity; - } - @Override - public void display(Position pos, String message, Severity _severity) { - //System.err.println("Display pos:"+pos+"; msg:"+message+"; severity:"+_severity); + public void info0(Position pos, String message, Severity severity, boolean force) { + //System.err.println("info0 pos:"+pos+"; msg:"+message+"; severity:"+severity); String label = ""; - int severity = severityRank(_severity); - if (severity == INFO && !Game.getInstance().isDebugEnabled()) + boolean isInfo = severity == INFO(); + boolean isWarning = severity == WARNING(); + boolean isError = severity == ERROR(); + if (!isInfo && !isWarning && !isError) + throw new RuntimeException("Got an unknown severity: "+severity+". Please adapt the PLM to this new version of scala (or whatever)."); + + if (isInfo && !Game.getInstance().isDebugEnabled()) return; - if (severity == WARNING) + if (isWarning) label = "warning: "; - if (severity == ERROR) - label = "error: "; + if (isError) + label = "error: "; - counts[severity]++; - int lineNum = -1; try { lineNum = pos.line() - offset; @@ -244,19 +234,5 @@ public void reset() { super.reset(); messages.removeAllElements(); } - - @Override - public int count(Object o) { - return counts[severityRank((Severity) o)]; - } - @Override - public void resetCount(Object o) { - counts[severityRank((Severity) o)] = 0; - } - @Override - public void info0(Position pos, String msg, Object o, boolean force) { - Severity s = (Severity) o; - display(pos, msg, s); - } } } \ No newline at end of file diff --git a/src/plm/core/model/Game.java b/src/plm/core/model/Game.java index 09eec544e..ddccc2019 100644 --- a/src/plm/core/model/Game.java +++ b/src/plm/core/model/Game.java @@ -161,7 +161,7 @@ private Game() { if (checkScala()) System.err.println(i18n.tr("Scala is usable on your machine. Congratulations.")); else - System.err.println(i18n.tr("Please install Scala version 2.11 or higher to use it in the PLM.")); + System.err.println(i18n.tr("Please install Scala version 2.12 or higher to use it in the PLM.")); if (checkPython()) System.err.println(i18n.tr("Jython is usable on your machine. Congratulations.")); else @@ -237,11 +237,11 @@ private boolean checkScala() { return canScala; } - if (version.contains("version 2.10") || version.contains("version 2.11")) { + if (version.contains("version 2.12") || version.contains("version 2.13")) { canScala = true; return canScala; } else { - scalaError = i18n.tr("Scala is too ancient. Found {0} while I need 2.10 or higher.",version); + scalaError = i18n.tr("Scala is too ancient. Found {0} while I need 2.12 or higher.",version); System.err.println(scalaError); return canScala; } @@ -1002,7 +1002,7 @@ public void setProgramingLanguage(ProgrammingLanguage newLanguage) { if (isValidProgLanguage(newLanguage)) { //System.out.println("Switch programming language to "+newLanguage); if (newLanguage.equals(Game.SCALA) && !canScala) { - JOptionPane.showMessageDialog(null, i18n.tr("Please install Scala version 2.11 or higher to use it in the PLM.\n\n")+scalaError , + JOptionPane.showMessageDialog(null, i18n.tr("Please install Scala version 2.12 or higher to use it in the PLM.\n\n")+scalaError , i18n.tr("Scala is missing"), JOptionPane.ERROR_MESSAGE); return; } diff --git a/src/plm/core/model/tracking/GitUtils.java b/src/plm/core/model/tracking/GitUtils.java index dff97c10e..e592bab0c 100644 --- a/src/plm/core/model/tracking/GitUtils.java +++ b/src/plm/core/model/tracking/GitUtils.java @@ -127,7 +127,9 @@ public boolean checkoutUserBranch(String userBranchHash) { public void mergeRemoteIntoLocalBranch(String userBranchHash) throws Exception { try { - MergeResult res = git.merge().setCommit(true).setFastForward(MergeCommand.FastForwardMode.FF).setStrategy(MergeStrategy.RECURSIVE).include(git.getRepository().getRef("refs/remotes/origin/"+userBranchHash)).call(); + // jgit 6.x: Repository.getRef(String) was removed; exactRef() is + // the replacement for fully-qualified ref names like this one. + MergeResult res = git.merge().setCommit(true).setFastForward(MergeCommand.FastForwardMode.FF).setStrategy(MergeStrategy.RECURSIVE).include(git.getRepository().exactRef("refs/remotes/origin/"+userBranchHash)).call(); if(res.getMergeStatus() == MergeResult.MergeStatus.FAST_FORWARD) { System.out.println(Game.i18n.tr("Last session data successfully retrieved.")); @@ -379,6 +381,9 @@ public void dispose() { } public Ref getRepoRef(String branch) throws IOException { - return git.getRepository().getRef(branch); + // jgit 6.x: Repository.getRef(String) was removed. findRef() keeps the + // old search semantics (tries short names under refs/heads, refs/tags, + // etc.); use exactRef() instead if only fully-qualified names are passed. + return git.getRepository().findRef(branch); } } diff --git a/src/plm/test/git/GitSpyTest.java b/src/plm/test/git/GitSpyTest.java index b2c9224bf..ef99992f1 100644 --- a/src/plm/test/git/GitSpyTest.java +++ b/src/plm/test/git/GitSpyTest.java @@ -19,7 +19,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.xnap.commons.i18n.I18nFactory; import plm.core.lang.ProgrammingLanguage; diff --git a/src/plm/test/gui/MainFrameSmokeTest.java b/src/plm/test/gui/MainFrameSmokeTest.java new file mode 100644 index 000000000..87634e9fa --- /dev/null +++ b/src/plm/test/gui/MainFrameSmokeTest.java @@ -0,0 +1,41 @@ +package plm.test.gui; + +import org.assertj.swing.edt.GuiActionRunner; +import org.assertj.swing.fixture.FrameFixture; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import plm.core.model.Game; +import plm.core.ui.MainFrame; + +/** + * GUI smoke test: launch PLM's main window and check that it actually comes up. + * + * Run under a display (the CI test job uses xvfb on Linux and the native display + * on Windows/macOS), this drives the full Swing stack -- not just the headless + * engine initialisation the other tests do. + */ +public class MainFrameSmokeTest { + + private FrameFixture window; + + @Before + public void setUp() { + Game.getInstance(); // build the model (also initialises the languages) + MainFrame frame = GuiActionRunner.execute(() -> MainFrame.getInstance()); + window = new FrameFixture(frame); + window.show(); + } + + @Test + public void theMainWindowComesUp() { + window.requireVisible(); + } + + @After + public void tearDown() { + if (window != null) + window.cleanUp(); + } +}