1   /* ===================================================================
2    * Copyright 2002-04 SRI International.
3    * Released under the MOZILLA PUBLIC LICENSE Version 1.1
4    * which can be obtained at http://www.mozilla.org/MPL/MPL-1.1.html
5    * This software is distributed on an "AS IS"
6    * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
7    * See the License for the specific language governing rights and
8    * limitations under the License.
9    * =================================================================== */
10  package com.sri.emo.controller;
11  
12  import java.util.HashMap;
13  import java.util.Iterator;
14  import java.util.List;
15  import java.util.Map;
16  import java.util.Vector;
17  import com.jcorporate.expresso.core.controller.Block;
18  import com.jcorporate.expresso.core.controller.ControllerException;
19  import com.jcorporate.expresso.core.controller.ErrorCollection;
20  import com.jcorporate.expresso.core.controller.ExpressoResponse;
21  import com.jcorporate.expresso.core.controller.Input;
22  import com.jcorporate.expresso.core.controller.NonHandleableException;
23  import com.jcorporate.expresso.core.controller.Output;
24  import com.jcorporate.expresso.core.controller.Transition;
25  import com.jcorporate.expresso.core.db.DBException;
26  import com.jcorporate.expresso.services.test.ControllerTestFixture;
27  import com.jcorporate.expresso.services.test.TestSystemInitializer;
28  import com.sri.emo.wizard.selection.management.WizardStepController;
29  import com.sri.emo.dbobj.Node;
30  import com.sri.emo.dbobj.WizDefinition;
31  import com.sri.emo.dbobj.WizStep;
32  import com.sri.emo.test.DatabaseTestFixture;
33  import com.sri.emo.test.EmoTestSuite;
34  import com.sri.emo.wizard.expressoimpl.WizardController;
35  import com.sri.emo.wizard.selection.EmoSelectionWizard;
36  import junit.framework.TestCase;
37  
38  public class TestSelectionManager extends TestCase {
39      private DatabaseTestFixture model = null;
40      private ControllerTestFixture testFixture = null;
41  
42  
43      protected void setUp() throws Exception {
44          super.setUp();
45          model = new DatabaseTestFixture(TestSystemInitializer.getTestContext(),
46                  EmoTestSuite.class.getResourceAsStream("WizardTestData.xml"));
47          model.setUp();
48          testFixture = new ControllerTestFixture();
49      }
50  
51      protected void tearDown() throws Exception {
52          model.tearDown();
53          model = null;
54          testFixture = null;
55          super.tearDown();
56      }
57  
58      private WizDefinition getDefinedWizard() throws DBException {
59          WizDefinition def = new WizDefinition();
60          def.setField(WizDefinition.FLD_ID, 12);
61          def.retrieve();
62          return def;
63      }
64  
65  
66      /***
67       * Checks that there are no errors defined in the error collection.
68       *
69       * @param response The ExpressoResponse object.
70       * @throws ControllerException
71       */
72      static private void checkNoErrorsInErrorCollection(ExpressoResponse response) throws ControllerException {
73          assertTrue(response.getErrors() == null
74                  || response.getErrors().getErrorCount() == 0);
75      }
76  
77  
78      public void testRunAddWizardState() throws ControllerException, NonHandleableException, DBException {
79  
80          ExpressoResponse response = testFixture.invokeFacade(SelectionWizardManager.class,
81                  new HashMap(),
82                  SelectionWizardManager.STATE_PROMPT_ADDWIZARD);
83  
84          assertTrue(response != null);
85          checkNoErrorsInErrorCollection(response);
86          Input i = response.getInput("title");
87          assertTrue(i != null);
88          assertEquals("", i.getDefaultValue());
89  
90          i = response.getInput("wizardClass");
91          assertTrue(i != null);
92          assertEquals(com.sri.emo.wizard.selection.EmoSelectionWizard.class.
93                  getName(),
94                  i.getDefaultValue());
95  
96          i = response.getInput("summary");
97          assertTrue(i != null);
98          assertEquals("", i.getDefaultValue());
99  
100         Transition add = response.getTransition("save");
101         assertTrue(add != null);
102         assertEquals(SelectionWizardManager.class.getName(), add.getControllerObject());
103         assertEquals(SelectionWizardManager.STATE_DO_ADDWIZARD, add.getState());
104 
105     }
106 
107     public void testRunAddWizardWithBadParameters() throws ControllerException,
108             NonHandleableException, DBException {
109         WizDefinition wizdef = new WizDefinition();
110         int count = wizdef.count();
111 
112         ExpressoResponse response = testFixture.invokeFacade(SelectionWizardManager.class,
113                  new HashMap(),
114                 SelectionWizardManager.STATE_DO_ADDWIZARD);
115         assertTrue(response != null);
116         checkErrorsAndNotAdded(response, wizdef, count);
117 
118         //Check with object not of Wizard interface
119         Map parameters = new HashMap();
120         parameters.put("wizardClass", "java.lang.Object");
121         response = testFixture.invokeFacade(SelectionWizardManager.class,
122                 parameters, SelectionWizardManager.STATE_DO_ADDWIZARD);
123         checkErrorsAndNotAdded(response, wizdef, count);
124 
125         //Check with bogus wizard object.
126         parameters.clear();
127         parameters.put("wizardClass", "org.example.NotRealObject");
128         response = testFixture.invokeFacade(SelectionWizardManager.class,
129                 parameters, SelectionWizardManager.STATE_DO_ADDWIZARD);
130         checkErrorsAndNotAdded(response, wizdef, count);
131 
132         //Check with no title.
133         parameters.clear();
134         parameters.put("summary", "A bogus definition");
135         parameters.put("wizardClass",
136                 com.sri.emo.wizard.defaults.SequentialWizard.class.getName());
137         response = testFixture.invokeFacade(SelectionWizardManager.class,
138                 parameters, SelectionWizardManager.STATE_DO_ADDWIZARD);
139         checkErrorsAndNotAdded(response, wizdef, count);
140 
141         //Check form cache
142         Input i = response.getInput("summary");
143         assertTrue(i != null);
144         assertEquals("A bogus definition", i.getDefaultValue());
145 
146     }
147 
148     /***
149      * Checks that there were errors generated in the ErrorCollection and
150      * that no WizardDefinitions were added to the underlying data model.
151      *
152      * @param response      ExpressoResponse for the request.
153      * @param wizdef        A preconstructed WizDefinition object to check count.
154      * @param originalCount the result of WizDefinition.count() before the
155      *                      request.
156      * @throws ControllerException upon controller error.
157      * @throws DBException         upon database access error.
158      */
159     protected void checkErrorsAndNotAdded(ExpressoResponse response, WizDefinition wizdef, int originalCount) throws ControllerException,
160             DBException {
161         ErrorCollection ec = response.getErrors();
162         assertTrue(ec != null);
163         assertTrue("Should have errors", ec.getErrorCount() > 0);
164         assertTrue("Should have no more wizards added",
165                 originalCount == wizdef.count());
166     }
167 
168     public void testRunCompleteAddState() throws ControllerException, NonHandleableException, DBException {
169         WizDefinition wizdef = new WizDefinition();
170         int count = wizdef.count();
171         final String TITLE = "Another Test Wizard Title";
172         Map params = new HashMap();
173         params.put("title", TITLE);
174         params.put("summary", "Another Test Wizard Definition");
175         params.put("wizardClass",
176                 com.sri.emo.wizard.selection.EmoSelectionWizard.class.getName());
177         ExpressoResponse response = testFixture.invokeFacade(SelectionWizardManager.class,
178             params, SelectionWizardManager.STATE_DO_ADDWIZARD);
179         assertTrue(response != null);
180         checkNoErrorsInErrorCollection(response);
181         assertEquals(SelectionWizardManager.STATE_PROMPT_EDIT,
182                 response.getCurrentState().getName());
183         assertEquals((count + 1), wizdef.count());
184 
185         WizDefinition def2 = new WizDefinition();
186         def2.setField(WizDefinition.FLD_NAME, TITLE);
187         assertTrue(def2.find());
188         assertEquals(EmoSelectionWizard.class.getName(),
189                 def2.getWizardClass());
190 
191     }
192 
193 
194     public void testRunEditWizardState() throws ControllerException,
195             NonHandleableException, DBException {
196         String idString = getDefinedWizard().getId();
197         Map params = new HashMap();
198         params.put(WizardController.WIZ_PARAMETER_ID, idString);
199 
200         ExpressoResponse response = testFixture.invokeFacade(SelectionWizardManager.class,
201                 params,
202                 SelectionWizardManager.STATE_PROMPT_EDIT);
203 
204         assertTrue(response != null);
205         checkNoErrorsInErrorCollection(response);
206         Input i = response.getInput("title");
207         assertTrue(i != null);
208         assertEquals("Pick A Movie", i.getDefaultValue());
209 
210         i = response.getInput("wizardClass");
211         assertTrue(i != null);
212         assertEquals(EmoSelectionWizard.class.getName(),
213                 i.getDefaultValue());
214 
215         i = response.getInput("summary");
216         assertTrue(i != null);
217         assertEquals("Allows you to choose which movie you wish to view",
218                 i.getDefaultValue());
219 
220         Transition add = response.getTransition("save");
221         assertTrue(add != null);
222         assertEquals(SelectionWizardManager.class.getName(), add.getControllerObject());
223         assertEquals(SelectionWizardManager.STATE_DO_EDIT, add.getState());
224 
225         Block steps = response.getBlock("steps");
226         checkGeneratedSteps(steps);
227 
228         Block decisionMatrix = response.getBlock("decisionMatrix");
229         assertTrue(decisionMatrix != null);
230         //There had BETTER be a decision matrix values for this
231         //particular wizard!
232         assertTrue(decisionMatrix.getNestedOrNull() != null);
233 
234         validateDecisionMatrix(decisionMatrix);
235 
236     }
237 
238 
239     /***
240      * What this function does is check all exId values.  If they exist,
241      * make sure that there's an appropriate node label next to it and checks
242      * its value.
243      *
244      * @param matrix Block the block to check.
245      * @return Map a list of Inputs for the decision matrix for further
246      *         testing keyed by input name.
247      * @throws DBException         upon database error.
248      * @throws ControllerException upon controller error.
249      * @todo Validate the Decision Matrix's results against the
250      * values retrieved by the controller.
251      */
252     protected Map validateDecisionMatrix(Block matrix) throws DBException
253             , ControllerException {
254         int counter = 0;
255 
256         boolean done = false;
257 
258         Block header = matrix.getBlock("header");
259         assertTrue(header != null);
260         Map returnValue = new HashMap();
261 
262         Block items = matrix.getBlock("items");
263 
264         while (!done) {
265             Block oneRow = items.getBlock("Row" + counter);
266             if (oneRow == null) {
267                 done = true;
268                 continue;
269             }
270 
271             Vector nestedOutputs = oneRow.getOutputs();
272             for (int i = 0; i < nestedOutputs.size(); i++) {
273                 Output oneOutput = (Output) nestedOutputs.get(i);
274                 if (i == 0) {
275                     assertEquals("" + counter + ")", oneOutput.getContent());
276                 } else {
277                     /***
278                      * @todo Check the actual value of this item.
279                      */
280                     assertTrue(oneOutput.getContent() != null);
281                 }
282             }
283 
284             Input oneInput = oneRow.getInput("exId" + counter);
285             returnValue.put("exId" + counter, oneInput);
286             if (oneInput.getDefaultValue() != null
287                     && oneInput.getDefaultValue().length() > 0) {
288 
289                 try {
290                     int number = Integer.parseInt(oneInput.getDefaultValue());
291                     System.out.println("Parsing node number: " + number);
292                     Output label = (Output) oneInput.getNested("nodeLabel");
293 
294                     assertTrue(label.getContent() != null);
295                     if (!label.getContent().startsWith("**[")) {
296                         Node n = new Node();
297                         n.setField(Node.NODE_ID, oneInput.getDefaultValue());
298                         n.retrieve();
299                         assertEquals(n.getNodeTitle(), label.getContent());
300                     } else {
301                         try {
302                             Node n = new Node();
303                             n.setField(Node.NODE_ID
304                                     , oneInput.getDefaultValue());
305                             n.retrieve();
306                             fail("Node label indicates an error and we "
307                                     + "were able to retrieve it: "
308                                     + oneInput.getName() + "["
309                                     + oneInput.getDefaultValue() + "]");
310                         } catch (DBException ex) {
311                         	assertNotNull(ex.getMessage());
312                             //a-ok, we want to make sure that if there's
313                             //an error, we really couldn't get at the node.
314                         }
315 
316                     }
317                 } catch (NumberFormatException ex1) {
318                 	assertNotNull(ex1.getMessage());
319                     //Continue, we had a bad value, we skip the
320                     //checking of the outputs.
321                 }
322             }
323 
324             counter++;
325         }
326 
327         return returnValue;
328     }
329 
330     protected void checkGeneratedSteps(Block steps) throws
331             NumberFormatException {
332         assertTrue(steps.getNested().size() == 3);
333         int counter = 0;
334         for (Iterator iterator = steps.getNestedIterator()
335                 ; iterator.hasNext();) {
336 
337             Block oneRow = (Block) iterator.next();
338             Output index = oneRow.getOutput("index");
339             assertTrue(index != null);
340             assertTrue(index.getContent() != null);
341             assertTrue(Integer.parseInt(index.getContent()) > 0);
342 
343             Transition delete = oneRow.getTransition("delete");
344             assertTrue(delete != null);
345             assertEquals(WizardStepController.STATE_PROMPT_DELETE,
346                     delete.getState());
347             assertTrue(delete.getParam(WizardController
348                     .WIZ_PARAMETER_ID) != null);
349             assertTrue(delete.getLabel() != null);
350 
351             if (counter != 0) {
352                 Transition up = oneRow.getTransition("up");
353                 assertTrue(up != null);
354                 assertEquals(WizardStepController.STATE_ORDERUP, up.getState());
355                 assertTrue(up.getParam(WizardController
356                         .WIZ_PARAMETER_ID) != null);
357             } else {
358                 Transition up = oneRow.getTransition("up");
359                 assertTrue(up == null);
360             }
361 
362             if (iterator.hasNext()) {
363                 Transition down = oneRow.getTransition("down");
364                 assertTrue(down != null);
365                 assertEquals(WizardStepController.STATE_ORDERDOWN,
366                         down.getState());
367                 assertTrue(down.getParam(WizardController
368                         .WIZ_PARAMETER_ID) != null);
369             } else {
370                 Transition down = oneRow.getTransition("down");
371                 assertTrue(down == null);
372 
373             }
374             counter++;
375         }
376     }
377 
378 
379     public void testRunEditWizardStateWithNoStepsDefined() throws
380             ControllerException, NonHandleableException, DBException {
381 
382         //Delete all the steps for the wizard from the model and now try
383         //it
384         String idString = getDefinedWizard().getId();
385         List definitions = getDefinedWizard().getPageDefinitions();
386         for (Iterator i = definitions.iterator(); i.hasNext();) {
387             WizStep oneStep = (com.sri.emo.dbobj.WizStep) i.next();
388             oneStep.delete(true);
389         }
390 
391         Map params = new HashMap();
392         params.put(WizardController.WIZ_PARAMETER_ID, idString);
393 
394         ExpressoResponse response = testFixture
395                 .invokeFacade(SelectionWizardManager.class, params,
396                         SelectionWizardManager.STATE_PROMPT_EDIT);
397 
398         checkNoErrorsInErrorCollection(response);
399 
400         Block steps = response.getBlock("steps");
401         assertTrue(steps != null);
402         assertTrue(steps.getNested().size() == 0);
403 
404         Block decisionMatrix = response.getBlock("decisionMatrix");
405         assertTrue(decisionMatrix != null);
406         assertTrue(decisionMatrix.getNested().size() == 0);
407     }
408 
409 
410     public void testRunCompleteUpdateState() throws ControllerException,
411             NonHandleableException, DBException {
412 
413         //Delete all the steps for the wizard from the model and now try
414         //it
415         String idString = getDefinedWizard().getId();
416 
417         Map params = new HashMap();
418 
419         final String TITLE = "Another Fine Wizard";
420         final String SUMMARY = "Yes, this really is a fine wizard";
421 
422         params.put(WizardController.WIZ_PARAMETER_ID, idString);
423         params.put("title", TITLE);
424         params.put("summary", SUMMARY);
425         params.put("wizardClass", com.sri.emo.wizard.defaults
426                 .SequentialWizard.class.getName());
427 
428         com.sri.emo.dbobj.WizStep steps = new com.sri.emo.dbobj.WizStep();
429         steps.setField(com.sri.emo.dbobj.WizStep.FLD_WIZID, idString);
430         List previousSteps = steps.searchAndRetrieveList(WizStep.FLD_ID);
431 
432         ExpressoResponse response = testFixture
433                 .invokeFacade(SelectionWizardManager.class, params,
434                         SelectionWizardManager.STATE_DO_EDIT);
435 
436         checkNoErrorsInErrorCollection(response);
437 
438         WizDefinition wizDef = new WizDefinition();
439         wizDef.setField(WizDefinition.FLD_ID, idString);
440         wizDef.retrieve();
441 
442         assertEquals(TITLE, wizDef.getWizName());
443         assertEquals(SUMMARY, wizDef.getSummary());
444         assertEquals(com.sri.emo.wizard.defaults.SequentialWizard
445                 .class.getName(),
446                 wizDef.getWizardClass());
447 
448         //Validate that the wizard steps are correctly complete.
449         //They should have not changed during wizard save.
450         com.sri.emo.dbobj.WizStep afterSteps = new com.sri.emo.dbobj.WizStep();
451         afterSteps.setField(com.sri.emo.dbobj.WizStep.FLD_WIZID, idString);
452         List allAfterSteps = afterSteps.searchAndRetrieveList(WizStep.FLD_ID);
453         assertEquals(previousSteps.size(), allAfterSteps.size());
454 
455         for (int i = 0; i < allAfterSteps.size(); i++) {
456             assertEquals(previousSteps.get(i), allAfterSteps.get(i));
457         }
458     }
459 
460     public void testDecisionMatrixWithMultipleUpdates() throws ControllerException,
461             NonHandleableException, DBException {
462         WizDefinition def = getDefinedWizard();
463         //Delete all the steps for the wizard from the model and now try
464         //it
465         String idString = def.getId();
466 
467         Map params = new HashMap();
468 
469         //We set up with a good node value.
470         params.put(WizardController.WIZ_PARAMETER_ID, idString);
471         params.put("title", def.getWizName());
472         params.put("summary", def.getSummary());
473         params.put("wizardClass", def.getWizardClass());
474         params.put("exId0", "12");
475 
476         ExpressoResponse response = testFixture.invokeFacade(SelectionWizardManager.class, params,
477                 SelectionWizardManager.STATE_DO_EDIT);
478 
479         checkNoErrorsInErrorCollection(response);
480 
481         //Now go back and check the UI
482         Map parms2 = new HashMap();
483         parms2.put(WizardController.WIZ_PARAMETER_ID, idString);
484         response = testFixture.invokeFacade(SelectionWizardManager.class, parms2,
485                 SelectionWizardManager.STATE_PROMPT_EDIT);
486         checkNoErrorsInErrorCollection(response);
487 
488         Block decisionMatrix = response.getBlock("decisionMatrix");
489         assertTrue(decisionMatrix != null);
490         Map result = validateDecisionMatrix(decisionMatrix);
491         Input id0 = (Input) result.get("exId0");
492         assertTrue(id0 != null);
493         assertEquals("12", id0.getDefaultValue());
494 
495     }
496 
497     public void testDecisionMatrixUpdate() throws ControllerException,
498             NonHandleableException, DBException {
499 
500         WizDefinition def = getDefinedWizard();
501         //Delete all the steps for the wizard from the model and now try
502         //it
503         String idString = def.getId();
504 
505         Map params = new HashMap();
506 
507         //We set up with a good node value.
508         params.put(WizardController.WIZ_PARAMETER_ID, idString);
509         params.put("title", def.getWizName());
510         params.put("summary", def.getSummary());
511         params.put("wizardClass", def.getWizardClass());
512         params.put("exId0", "12");
513 
514         ExpressoResponse response = testFixture.invokeFacade(SelectionWizardManager.class, params,
515                 SelectionWizardManager.STATE_DO_EDIT);
516 
517         checkNoErrorsInErrorCollection(response);
518 
519         //Now go back and check the UI
520         Map parms2 = new HashMap();
521         parms2.put(WizardController.WIZ_PARAMETER_ID, idString);
522         response = testFixture.invokeFacade(SelectionWizardManager.class, parms2,
523                 SelectionWizardManager.STATE_PROMPT_EDIT);
524         checkNoErrorsInErrorCollection(response);
525 
526         Block decisionMatrix = response.getBlock("decisionMatrix");
527         assertTrue(decisionMatrix != null);
528         Map result = validateDecisionMatrix(decisionMatrix);
529         Input id0 = (Input) result.get("exId0");
530         assertTrue(id0 != null);
531         assertEquals("12", id0.getDefaultValue());
532     }
533 
534 
535     public void testDecisionMatrixUpdateWithBadValues() throws
536             ControllerException,
537             NonHandleableException, DBException {
538 
539         WizDefinition def = getDefinedWizard();
540         //Delete all the steps for the wizard from the model and now try
541         //it
542         String idString = def.getId();
543 
544         Map params = new HashMap();
545 
546         //We set up with a good node value.
547         params.put(WizardController.WIZ_PARAMETER_ID, idString);
548         params.put("title", def.getWizName());
549         params.put("summary", def.getSummary());
550         params.put("wizardClass", def.getWizardClass());
551         params.put("exId0", "abdls");
552         params.put("exId1", "101001");
553 
554         ExpressoResponse response = testFixture.invokeFacade(SelectionWizardManager.class, params,
555                 SelectionWizardManager.STATE_DO_EDIT);
556 
557         assertTrue(response.getErrors().getErrorCount() >= 2);
558 
559         Block decisionMatrix = response.getBlock("decisionMatrix");
560         Map result = validateDecisionMatrix(decisionMatrix);
561         Input id0 = (Input) result.get("exId0");
562         assertTrue(id0 != null);
563         assertEquals("abdls", id0.getDefaultValue());
564 
565         Input id1 = (Input) result.get("exId1");
566         assertTrue(id1 != null);
567         assertEquals("101001", id1.getDefaultValue());
568         Output errorMessage = (Output) id1.getNested("nodeLabel");
569         assertTrue(errorMessage.getContent().startsWith("**["));
570     }
571 }