1 | package org.greenstone.gsdl3.testing;
|
---|
2 |
|
---|
3 | import java.io.File;
|
---|
4 | import java.util.Map;
|
---|
5 | import java.util.regex.*;
|
---|
6 | import java.awt.Component;
|
---|
7 |
|
---|
8 | // only JUnit and JAssert-Swing, no Selenium in this class
|
---|
9 | import org.junit.Assert;
|
---|
10 | import org.assertj.swing.fixture.*;
|
---|
11 | import org.assertj.swing.timing.Timeout ;
|
---|
12 |
|
---|
13 |
|
---|
14 | // GLI imports
|
---|
15 | import org.greenstone.gatherer.Gatherer;
|
---|
16 | import org.greenstone.gatherer.GathererProg; // main GLI class we'll be testing
|
---|
17 | import org.greenstone.gatherer.Dictionary; // access to display strings
|
---|
18 |
|
---|
19 |
|
---|
20 | // Java GUI testing with AssertJ Swing
|
---|
21 | import org.assertj.swing.junit.testcase.AssertJSwingJUnitTestCase;
|
---|
22 | import org.assertj.swing.fixture.*;
|
---|
23 | import org.assertj.swing.edt.GuiActionRunner;
|
---|
24 | import org.assertj.swing.core.Robot;
|
---|
25 |
|
---|
26 |
|
---|
27 | // static imports
|
---|
28 | import static org.assertj.swing.launcher.ApplicationLauncher.*;
|
---|
29 | import static org.assertj.swing.finder.WindowFinder.findFrame;
|
---|
30 |
|
---|
31 | /*
|
---|
32 | * Utility class containing helper functions for GLI GUI testing using AsssertJ Swing
|
---|
33 | */
|
---|
34 |
|
---|
35 | public class GSGUITestingUtil
|
---|
36 | {
|
---|
37 | public static FrameFixture window = null;
|
---|
38 |
|
---|
39 | public static final boolean PAUSE_ON = true;
|
---|
40 |
|
---|
41 | public static final int SECOND = 1000; // 1000 ms
|
---|
42 |
|
---|
43 | public static final String DOWNLOAD_PANE = "Download";
|
---|
44 | public static final String GATHER_PANE = "Gather";
|
---|
45 | public static final String ENRICH_PANE = "Enrich";
|
---|
46 | public static final String DESIGN_PANE = "Design";
|
---|
47 | public static final String CREATE_PANE = "Create";
|
---|
48 | public static final String FORMAT_PANE = "Format";
|
---|
49 |
|
---|
50 |
|
---|
51 | /************** NEEDED FOR TESTING *************/
|
---|
52 | // There's now a new method in GLI: GUIManager.setNamesRecursively()
|
---|
53 | // that attempts to recursively call setName() on visible GUI components so that we
|
---|
54 | // can have easier access to those GUI components when testing here through their names
|
---|
55 |
|
---|
56 | /****************************** APPLICATION *******************************/
|
---|
57 | public static void PAUSE() {
|
---|
58 | PAUSE(5);
|
---|
59 | }
|
---|
60 | public static void PAUSE(int seconds) {
|
---|
61 | if(!PAUSE_ON) return; // ignore calls to PAUSE
|
---|
62 |
|
---|
63 | // wait a couple of seconds again?
|
---|
64 | try{
|
---|
65 | Thread.sleep(seconds*SECOND);
|
---|
66 | } catch(Exception e) {
|
---|
67 | e.printStackTrace();
|
---|
68 | }
|
---|
69 | }
|
---|
70 |
|
---|
71 | //public static void setWindow(FrameFixture w) { window = w; } // if we want to null window
|
---|
72 |
|
---|
73 | public static void runGLI() {
|
---|
74 | //GathererProg frame = GuiActionRunner.execute(() -> new GathererProg());
|
---|
75 |
|
---|
76 | // IMPORTANT, note the call to 'robot()': must use the Robot from AssertJSwingJUnitTestCase
|
---|
77 | //window = new FrameFixture(robot(), frame);
|
---|
78 | //window.show(); // shows the frame to test
|
---|
79 |
|
---|
80 | // Instead, we'll be launching GLI and then getting a ref to the launched app window:
|
---|
81 |
|
---|
82 | // Launch GathererProg.java's main() method
|
---|
83 | // See https://joel-costigliola.github.io/assertj/assertj-swing-launch.html
|
---|
84 |
|
---|
85 | String GSDLOS = System.getenv("GSDLOS");
|
---|
86 | String GSDLHOME = System.getenv("GSDLHOME");
|
---|
87 | String GSDL3HOME = System.getenv("GSDL3HOME");
|
---|
88 | String GSDL3SRCHOME = System.getenv("GSDL3SRCHOME");
|
---|
89 | application("org.greenstone.gatherer.GathererProg").withArgs(
|
---|
90 | "-gsdl", GSDLHOME,
|
---|
91 | "-gsdlos", GSDLOS,
|
---|
92 | "-gsdl3", GSDL3HOME,
|
---|
93 | "-gsdl3src", GSDL3SRCHOME,
|
---|
94 | "-testing_mode").start();
|
---|
95 | // The -testing_mode flag passed into GLI above is a special flag
|
---|
96 | // that calls GLI's TestingPreparating.setNamesRecursively()
|
---|
97 | // to help testing by calling setName() on GUI components.
|
---|
98 | }
|
---|
99 |
|
---|
100 | public static void exitGLI() {
|
---|
101 | openMenuItem("file", "exit");
|
---|
102 | }
|
---|
103 |
|
---|
104 | // Gets a ref to the main window (FrameFixture) of a running GLI
|
---|
105 | public static FrameFixture getGLIApplicationWindow(Robot robot) {
|
---|
106 | // locate and set the internal FrameFixture member variable 'window' and return a handle to it
|
---|
107 | window = findFrame("GUIManager").using(robot); // GLI application JFrame's name is set to its classname, 'GUIManager'
|
---|
108 |
|
---|
109 | // https://joel-costigliola.github.io/assertj/swing/api/index.html?org/assertj/swing/launcher/ApplicationLauncher.html
|
---|
110 | // "To change the speed of a GUI test, you need to change the values of both delayBetweenEvents and eventPostingDelay."
|
---|
111 | //robot.settings().delayBetweenEvents(50);
|
---|
112 | //robot.settings().eventPostingDelay(2*SECOND); // annoying, after every click!
|
---|
113 |
|
---|
114 | return window;
|
---|
115 | }
|
---|
116 |
|
---|
117 | /****************************** BASICS *******************************/
|
---|
118 |
|
---|
119 |
|
---|
120 | //https://joel-costigliola.github.io/assertj/swing/api/org/assertj/swing/fixture/FrameFixture.html
|
---|
121 | public static void switchToPane(String pane) {
|
---|
122 | String paneLabel = Dictionary.get("GUI." + pane); // e.g. GUI.Enrich
|
---|
123 | //JPanelFixture tab = window.panel(pane); // this just gets us the JPanel of controls within
|
---|
124 | JTabbedPaneFixture tab = window.tabbedPane("GUIManager.tab_pane");
|
---|
125 | tab.selectTab(paneLabel); // select tab by its title
|
---|
126 | }
|
---|
127 | public static void openMenuItem(String menu, String subMenu) {
|
---|
128 | /*String menuLabel = Dictionary.get("Menu." + menu); // e.g. Menu.File
|
---|
129 | window.menuItem(menuLabel).click(); //JMenuItemFixture.click()
|
---|
130 | String subMenuLabel = Dictionary.get(menuLabel + "_" + subMenu); // e.g. Menu.File_Open
|
---|
131 | window.menuItem(subMenuLabel).click();*/
|
---|
132 | window.menuItem("MenuBar."+menu).click();
|
---|
133 | window.menuItem("MenuBar."+menu+"_"+subMenu).click();
|
---|
134 | }
|
---|
135 |
|
---|
136 | /*
|
---|
137 | public static void stealAnyLock() {
|
---|
138 | DialogFixture dialog = window.dialog("LockFileDialog");
|
---|
139 | if(dialog != null) {
|
---|
140 | dialog.button("LockFileDialog.ok_button").click();
|
---|
141 | }
|
---|
142 | }*/
|
---|
143 |
|
---|
144 |
|
---|
145 | // e.g. pane = Enrich,view=collection; pane = Gather, view = workspace (or collection)
|
---|
146 | public static void getFolderPath(String pane, String view, String folderPath) {}
|
---|
147 | public static void getFilePath(String pane, String view, String filePath) {}
|
---|
148 |
|
---|
149 | /**********************FILE MENU*******************************/
|
---|
150 | public static void setPrefs(String tab, Map params) {
|
---|
151 | openMenuItem("file", "options");
|
---|
152 |
|
---|
153 | }
|
---|
154 |
|
---|
155 | /**
|
---|
156 | * @param toMode must be the dictionary key for Preferences mode.
|
---|
157 | * Choose from Preferences.Mode.Assistant, Preferences.Mode.Librarian, Preferences.Mode.Expert
|
---|
158 | */
|
---|
159 | public static void changeUserMode(String toMode) {
|
---|
160 | openMenuItem("file", "options"); // click MenuBar.file -> MenuBar.file_options
|
---|
161 |
|
---|
162 | // switch to Mode tab
|
---|
163 | String paneLabel = Dictionary.get("Preferences.Mode");
|
---|
164 | DialogFixture dialog = window.dialog("Preferences");
|
---|
165 | JTabbedPaneFixture tab = window.tabbedPane("Preferences.tab_pane");
|
---|
166 | tab.selectTab(paneLabel); // select tab by its title
|
---|
167 |
|
---|
168 | String mode = "assistant"; // library assistant
|
---|
169 | if(toMode.contains("xpert")) {
|
---|
170 | mode = "expert";
|
---|
171 | } else if (toMode.endsWith("ibrarian")) {
|
---|
172 | mode = "librarian";
|
---|
173 | }
|
---|
174 | dialog.radioButton("Preferences."+mode+"_mode_radio_button").check(true);
|
---|
175 |
|
---|
176 | // apply and close dialog
|
---|
177 | dialog.button("Preferences.apply_button").click();
|
---|
178 | dialog.button("Preferences.ok_button").click();
|
---|
179 | }
|
---|
180 |
|
---|
181 |
|
---|
182 | public static void closeCollection(){
|
---|
183 | // Through componennt names, clicks on MenuBar.file then MenuBar.file_close
|
---|
184 | openMenuItem("file", "close");
|
---|
185 | }
|
---|
186 |
|
---|
187 | public static void deleteCollection(String collName) {
|
---|
188 | openMenuItem("file", "delete");
|
---|
189 | DialogFixture dialog = window.dialog("DeleteCollectionPrompt"); // could call window.dialg() too as there will be only one, unless GLI run in debug mode?
|
---|
190 |
|
---|
191 | JListFixture collection_list = dialog.list("DeleteCollectionPrompt.list");
|
---|
192 |
|
---|
193 | Pattern collNameRegex = Pattern.compile(".*"+collName+".*");
|
---|
194 | collection_list.selectItem(collNameRegex);
|
---|
195 |
|
---|
196 | collection_list.requireSelection(collNameRegex); // assert it exists and is selectable. Can't select (or delete) coll if it's open
|
---|
197 |
|
---|
198 | dialog.checkBox("DeleteCollectionPrompt.confirmation").check(true); // check checkbox to be sure to delete
|
---|
199 | dialog.button("DeleteCollectionPrompt.ok_button").click(); // delete button
|
---|
200 |
|
---|
201 | // A close confirmation optionPane dialog appears - click OK in it
|
---|
202 | dialog.optionPane().okButton().click();
|
---|
203 |
|
---|
204 | dialog.button("DeleteCollectionPrompt.close_button").click(); // close deleteColl dialog
|
---|
205 | }
|
---|
206 |
|
---|
207 | public static void saveCollection() {
|
---|
208 | openMenuItem("file", "save"); // MenuBar.file -> MenuBar.file_save
|
---|
209 | }
|
---|
210 |
|
---|
211 | public static void createCollection(String collTitle, String collDescription, String baseColl)
|
---|
212 | {
|
---|
213 | openMenuItem("file", "new");
|
---|
214 | DialogFixture dialog = window.dialog("col"); // GLI is unable to setName() of this dialog
|
---|
215 | // to NewCollectioNDetailsPrompt. Not sure why.
|
---|
216 |
|
---|
217 | dialog.textBox("NewCollectionDetailsPrompt.title").enterText(collTitle); // JTextField
|
---|
218 | if(collDescription != null && !collDescription.equals("")) {
|
---|
219 | // JTextArea description
|
---|
220 | dialog.textBox("NewCollectionDetailsPrompt.description").enterText(collDescription);
|
---|
221 | }
|
---|
222 |
|
---|
223 | // JComboBox base_collection
|
---|
224 | if(baseColl != null && !baseColl.equals("")) {
|
---|
225 | JComboBoxFixture baseCollBox = dialog.comboBox("NewCollectionDetailsPrompt.base_collection");
|
---|
226 | Pattern collNameRegex = Pattern.compile(".*"+baseColl+".*"); // comboBox should CONTAIN this string
|
---|
227 | baseCollBox.selectItem(collNameRegex);
|
---|
228 | baseCollBox.requireSelection(collNameRegex); // assert the baseColl name exists
|
---|
229 | }
|
---|
230 | dialog.button("NewCollectionDetailsPrompt.create_button").click();
|
---|
231 | }
|
---|
232 |
|
---|
233 | public static void loadCollection(String collName) {
|
---|
234 | openMenuItem("file", "open");
|
---|
235 | DialogFixture dialog = window.dialog("OpenCollectionDialog");
|
---|
236 | JListFixture collection_list = dialog.list("OpenCollectionDialog.collection_list");
|
---|
237 |
|
---|
238 | // See section 4.2 of http://www.vogella.com/tutorials/JavaRegularExpressions/article.html
|
---|
239 | // Apparently, testing Pattern "collName" expects it to match in entirety
|
---|
240 | // whereas testing ".*collName.*" will test the string contains this Pattern
|
---|
241 | Pattern collNameRegex = Pattern.compile(".*"+collName+".*");
|
---|
242 |
|
---|
243 | /*String[] items = collection_list.contents();
|
---|
244 | for(String item : items) {
|
---|
245 | System.err.println("@@@ ITEM: " + item);
|
---|
246 | }*/
|
---|
247 |
|
---|
248 |
|
---|
249 | //JListItemFixture collItem = collection_list.item(collNameRegex);
|
---|
250 | //collItem.click();
|
---|
251 | //collection_list.requireSelection(collNameRegex); // assert that the requested collection exists
|
---|
252 | //collItem.doubleClick();
|
---|
253 | collection_list.selectItem(collNameRegex);
|
---|
254 | collection_list.requireSelection(collNameRegex); // assert that the requested collection exists
|
---|
255 |
|
---|
256 |
|
---|
257 | /*String[] selections = collection_list.selection();
|
---|
258 | for(String s : selections) {
|
---|
259 | System.err.println("@@@ opening collection " + s);
|
---|
260 | }*/
|
---|
261 |
|
---|
262 | JListItemFixture selectedColl = collection_list.item(collNameRegex);
|
---|
263 | //collection_list.doubleClick(); // will double-click on last item regardless of what's selected
|
---|
264 | selectedColl.doubleClick();
|
---|
265 |
|
---|
266 | //steal any lock
|
---|
267 | /*
|
---|
268 | DialogFixture dialog = window.dialog("LockFileDialog");
|
---|
269 | if(dialog != null) {
|
---|
270 | dialog.button("LockFileDialog.ok_button").click();
|
---|
271 | }
|
---|
272 | */
|
---|
273 | }
|
---|
274 |
|
---|
275 | /**
|
---|
276 | * @param exportColl has to be internal GS collection name, e.g. lucene-jdbm-demo
|
---|
277 | * not public collection name like "Demo Collection".
|
---|
278 | */
|
---|
279 | public static void exportCollection(String exportToFormat, String exportColl)
|
---|
280 | {
|
---|
281 | openMenuItem("file", "exportas"); // Clicks MenuBar.file -> MenuBar.file_exportas
|
---|
282 |
|
---|
283 | DialogFixture dialog = window.dialog("ExportAsPrompt");
|
---|
284 | dialog.comboBox("ExportAsPrompt.saveas_combobox").selectItem(exportToFormat);
|
---|
285 |
|
---|
286 | Pattern collNameRegex = Pattern.compile(".*"+exportColl+".*");
|
---|
287 | JListFixture collection_list = dialog.list("ExportAsPrompt.list");
|
---|
288 | collection_list.selectItem(collNameRegex); //JList of collections
|
---|
289 | collection_list.requireSelection(collNameRegex); // check it exists
|
---|
290 |
|
---|
291 | dialog.button("ExportAsPrompt.ok_button").click(); // do export
|
---|
292 |
|
---|
293 | // first we see a progress dialog
|
---|
294 |
|
---|
295 | // Wait for subsequent export complete dialog
|
---|
296 | DialogFixture exportCompleteDialog = window.dialog("SimpleResultDialog", Timeout.timeout(30*SECOND));
|
---|
297 |
|
---|
298 | // non-modal dialog, so give it focus, so we can close it through its Close button
|
---|
299 | exportCompleteDialog.focus();
|
---|
300 |
|
---|
301 | //exportCompleteDialog.button().click();
|
---|
302 | exportCompleteDialog.button("SimpleResultDialog.GLIButton."+Dictionary.get("General.Close")).click(); // it only has a single button: "Close", still want to future proof if more buttons get added by specifying the particular button
|
---|
303 |
|
---|
304 |
|
---|
305 | // Close outer dialog too - cancel doubles as close button now that export is complete
|
---|
306 | dialog.button("ExportAsPrompt.cancel_button").click();
|
---|
307 |
|
---|
308 | File file = new File(System.getenv("GSDLHOME") + File.separator + "tmp" + File.separator + "exported_"+exportColl+"_"+exportToFormat);
|
---|
309 |
|
---|
310 | Assert.assertTrue(file.exists());
|
---|
311 | Assert.assertTrue(file.isDirectory());
|
---|
312 | }
|
---|
313 |
|
---|
314 | /*************** DESIGN ******************************/
|
---|
315 | public static void changeIndexer(String toIndexer) {}
|
---|
316 | public static void changeDB(String toDB) {}
|
---|
317 |
|
---|
318 | public static void configurePartitionIndex(String tab, Map params) {}
|
---|
319 |
|
---|
320 | public static void configurePlugin(String pluginName, Map params) {
|
---|
321 | }
|
---|
322 |
|
---|
323 | public static void configureClassifier(String classifierName, Map params) {}
|
---|
324 |
|
---|
325 | public static void configurePlugout(String plugoutName, Map params) {}
|
---|
326 |
|
---|
327 | // https://www.journaldev.com/1257/java-varargs
|
---|
328 | // https://www.geeksforgeeks.org/variable-arguments-varargs-in-java/
|
---|
329 | public static void keepOnlyPlugins(String ... plug_n) {}
|
---|
330 |
|
---|
331 | public static void removePlugs(String ... plug_n) {}
|
---|
332 |
|
---|
333 | /********************** CREATE PANEL ********************/
|
---|
334 | public static void buildOpenCollection() {}
|
---|
335 | public static void buildOpenCollection(boolean minimalRebuild) {}
|
---|
336 | public static void configureImportOptions(Map params) {}
|
---|
337 | public static void configureBuildOptions(Map params) {}
|
---|
338 |
|
---|
339 | public static void buildOutputContains(String ... n) {}
|
---|
340 |
|
---|
341 | /******************** GATHER PANE ********************/
|
---|
342 | public static void createWorkspaceShortcut(){}
|
---|
343 |
|
---|
344 | // in current open collection
|
---|
345 | public static void createCollectionSubfolder() {}
|
---|
346 |
|
---|
347 | public static void dragNDrop(String workspacePath, String collPath) {}
|
---|
348 |
|
---|
349 | /********************* ENRICH PANE ******************/
|
---|
350 | // docPath can be just docName or collectionSubfolder/Subfolder2/docName
|
---|
351 | public static void addMeta(String docPath, Map metanamesToValues) {}
|
---|
352 | public static void addFolderLevelMeta(String folderPath, Map metanamesToValues) {}
|
---|
353 |
|
---|
354 | /********************* DOWNLOAD PANE ******************/
|
---|
355 | // TODO: more functions needed here: e.g. serverInfo?
|
---|
356 | public static void download(String downloader, Map params) {}
|
---|
357 | public static void clearCache() {}
|
---|
358 | public static String serverInfo() {
|
---|
359 | return "";
|
---|
360 | }
|
---|
361 |
|
---|
362 | /********************* DOWNLOAD PANE ******************/
|
---|
363 | public static void formatGeneral(){}
|
---|
364 | public static void formatSearch() {}
|
---|
365 | public static void formatFeature(String featureName, String filename) {}
|
---|
366 | public static boolean isFormatFeatureXMLValid() {
|
---|
367 | return true;
|
---|
368 | }
|
---|
369 |
|
---|
370 |
|
---|
371 | /********************* GEMS ******************/
|
---|
372 |
|
---|
373 | // TODO:
|
---|
374 | public static void runGEMS() {}
|
---|
375 | public static void exitGEMS() {}
|
---|
376 | public static FrameFixture getGEMSApplicationWindow(Robot robot) {
|
---|
377 | // TODO: don't forget to set internal member variable called 'window' before returning it
|
---|
378 | return window;
|
---|
379 | }
|
---|
380 |
|
---|
381 | // Moving these working bits of code here, in case I can use them to right
|
---|
382 | // general get methods that make use of the GenericTypeMatcher method of accessing components
|
---|
383 | // See https://joel-costigliola.github.io/assertj/assertj-swing-lookup.html
|
---|
384 |
|
---|
385 | /*window = findFrame(new GenericTypeMatcher<JFrame>(JFrame.class) {
|
---|
386 | protected boolean isMatching(JFrame window) {
|
---|
387 | return window.getTitle().trim().startsWith(expectedWindowTitle)
|
---|
388 | && window.isShowing();
|
---|
389 | }
|
---|
390 | }).using(robot());
|
---|
391 | */
|
---|
392 | /*
|
---|
393 | JTabbedPaneFixture tab = window.tabbedPane(new GenericTypeMatcher<JTabbedPane>(JTabbedPane.class) {
|
---|
394 | @Override protected boolean isMatching(JTabbedPane tabPane) {
|
---|
395 | System.err.println("### trying for match");
|
---|
396 | //int index = GuiActionRunner.execute(() -> tabPane.getSelectedIndex());
|
---|
397 | int index = tabPane.getSelectedIndex();
|
---|
398 | String selectedTabTitle = tabPane.getTitleAt(index); //GuiActionRunner.execute(() -> tabPane.getTitleAt(index));
|
---|
399 | System.err.println("### GOT TITLE: " + selectedTabTitle);
|
---|
400 | return gatherPaneLabel.equals(selectedTabTitle);
|
---|
401 | }
|
---|
402 | });
|
---|
403 | */
|
---|
404 | }
|
---|