Index: gs3-extensions/testing/trunk/src/src/gstests/tutorials/RunGLITest.EDTcheckOff_NoHelp
===================================================================
--- gs3-extensions/testing/trunk/src/src/gstests/tutorials/RunGLITest.EDTcheckOff_NoHelp	(revision 32715)
+++ gs3-extensions/testing/trunk/src/src/gstests/tutorials/RunGLITest.EDTcheckOff_NoHelp	(revision 32715)
@@ -0,0 +1,192 @@
+package gstests.tutorials;
+
+/*
+Ctrl+Shift+A TO ABORT A RUNNING GUI-TEST CYCLE (won't abort Selenium/browser tests)
+
+Using AssertJ Swing to do Java GUI testing (of swing classes)
+- Obtain from: https://search.maven.org/search?q=assertj-swing-junit
+- Documentation: https://joel-costigliola.github.io/assertj/assertj-swing.html
+
+Alternatives to AssertJSwing (googled: automate java interface testing) suggested at
+https://sqa.stackexchange.com/questions/18554/open-source-tools-for-automation-of-java-gui-application-testing
+
+Event Dispatch Thread (EDT) pages:
+- https://joel-costigliola.github.io/assertj/assertj-swing-edt.html
+- https://web.archive.org/web/20120526191520/http://alexruiz.developerblogs.com/?p=160
+- https://web.archive.org/web/20130218063544/http://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html
+- https://stackoverflow.com/questions/2829364/java-difference-between-swingworker-and-swingutilities-invokelater
+
+Got AssertJ Swing from Maven Central Repository:
+https://search.maven.org/search?q=assertj-swing-junit
+-> http://central.maven.org/maven2/org/assertj/assertj-core/3.8.0/
+More jar files: http://repo1.maven.org/maven2/org/assertj/
+- http://repo1.maven.org/maven2/org/assertj/assertj-swing/3.8.0/
+- http://central.maven.org/maven2/org/assertj/assertj-core/3.8.0/
+
+API:
+https://joel-costigliola.github.io/assertj/swing/api/index.html
+
+JUNIT:
+- https://junit.org/junit4/faq.html#atests_2
+   How do I use a test fixture?
+- https://junit.org/junit4/faq.html#organize_3
+   How can I run setUp() and tearDown() code once for all of my tests?
+
+*/
+
+// Junit imports
+import org.junit.AfterClass;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+// GLI imports
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.GathererProg; // main GLI class we'll be testing
+import org.greenstone.gatherer.Dictionary; // access to display strings
+
+// Java GUI testing with AssertJ Swing
+import org.assertj.swing.junit.testcase.AssertJSwingJUnitTestCase;
+import org.assertj.swing.fixture.*;
+import org.assertj.swing.core.*; // Robot
+import org.assertj.swing.data.Index;
+
+// Selenium
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.firefox.FirefoxDriver;
+
+// Helper classes for selenium and AssertJ Swing tests
+import org.greenstone.gsdl3.testing.GSTestingUtil;
+import org.greenstone.gsdl3.testing.GSGUITestingUtil;
+
+// Java imports
+import javax.swing.*;
+
+// static imports
+import static org.greenstone.gsdl3.testing.GSGUITestingUtil.*;
+
+/**
+ * Class that will eventually go through all the Greenstone3 tutorials by running GLI and GEMS.
+ */
+public class RunGLITest {
+    // For aborting running test suite, with Ctrl+Shift+A by default
+    // https://joel-costigliola.github.io/assertj/assertj-swing-running.html
+    private static EmergencyAbortListener abortListener = EmergencyAbortListener.registerInToolkit();    
+    private static WebDriver _driver = new FirefoxDriver(); // for browser tests with selenium
+    private static Robot robot; // for Java GUI tests with assertj-swing
+    
+    private FrameFixture window;
+    
+    @BeforeClass
+    public static void setUpOnce() {
+	//FailOnThreadViolationRepaintManager.install();
+
+	// Need to have the robot before we can call runGLI()
+	// Robot is the class that controls/drives user input by taking control over the keyboard and mouse
+	robot = BasicRobot.robotWithNewAwtHierarchy();
+    }
+	
+
+    @Before
+    public void init()
+    {
+	// 1. Selenium
+	
+	//https://stackoverflow.com/questions/38676719/selenium-using-java-the-path-to-the-driver-executable-must-be-set-by-the-webdr
+	// GS3's build.xml would have set the webdriver.gecko.driver path System.Property to
+	// the location of Firefox' geckodriver executable when launching this test class already.
+	// So now we can continue to just do:
+	_driver.get(System.getProperty("SERVERURL"));
+    
+
+	// 2. assertj-swing	
+
+	// Run GLI and show the window	
+	// Launch GLI and then get a ref to the launched app window:
+	runGLI();
+
+	// IMPORTANT, note the call to 'robot()': must use the Robot from AssertJSwingJUnitTestCase base class
+	//window = findFrame("GUIManager").using(robot());
+	window = GSGUITestingUtil.getGLIApplicationWindow(robot);
+    }
+    
+    
+  @Test
+  public void testGLIRunning() {
+
+	
+      // waiting a few seconds for window, so we can see it
+      PAUSE(2);      
+    
+      System.err.println("@@@ First test: GLI Running");
+      
+      
+      String expectedWindowTitle = Gatherer.PROGRAM_NAME;
+
+            
+      String gatherPaneLabel = Dictionary.get("GUI.Gather");
+      System.err.println("@@@ Expecting label: " + gatherPaneLabel);
+      
+      System.err.println("@@@ Second test: that Gather panel is selected and has right title");
+      
+      JTabbedPaneFixture tab = window.tabbedPane("GUIManager.tab_pane");
+      
+      
+      tab.requireSelectedTab(Index.atIndex(1));
+      tab.requireTitle(gatherPaneLabel, Index.atIndex(1));
+      
+      // attempt to switch to enrich pane, uses static methods of GSGUITestingUtil
+      // through static import of that class
+      switchToPane(DOWNLOAD_PANE);
+
+      // For testing, want GLI to be in librarian mode by default
+      changeUserMode("librarian");
+
+      switchToPane(GATHER_PANE);
+      
+      loadCollection("lucene-jdbm-demo");
+
+      // wait a couple of seconds again?
+      PAUSE(2);      
+      closeCollection();
+      
+      createCollection("pinky", "Pinky was here", null);
+      closeCollection(); // collection must be closed in order to be deleted
+      deleteCollection("pinky");
+      
+      // wait a few of seconds again?
+      PAUSE(2);
+      
+      exportCollection("GreenstoneMETS", "lucene-jdbm-demo");
+
+      // Reset GLI to expert mode for regular GLI use
+      changeUserMode("expert");
+      
+      PAUSE(2);      
+      
+      switchToPane(GATHER_PANE);
+
+      //exitGLI(); //System.exit() on GLI won't allow quit to be called on Selenium's web _driver, why?
+      PAUSE(3);
+  }
+    
+    @After
+    public void tearDown() {
+	// call FrameFixture's cleanUp() which
+	// "Cleans up any used resources (keyboard, mouse, open windows and ScreenLock) used by this robot."
+	window.cleanUp();
+    }
+    
+    // Selenium
+    // called once and only once: to quit the firefox driver geckodriver
+    @AfterClass
+    public static void destroy()
+    {
+	abortListener.unregister(); // aborting assertJ-swing GUI tests
+	_driver.quit();
+    }
+}
