001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: /**
066: * TestController.java
067: *
068: * Copyright 2000, 2001 Jcorporate Ltd.
069: */package com.jcorporate.expresso.ext.controller;
070:
071: import com.jcorporate.expresso.core.controller.ControllerException;
072: import com.jcorporate.expresso.core.controller.ControllerRequest;
073: import com.jcorporate.expresso.core.controller.ControllerResponse;
074: import com.jcorporate.expresso.core.controller.DBController;
075: import com.jcorporate.expresso.core.controller.Input;
076: import com.jcorporate.expresso.core.controller.NonHandleableException;
077: import com.jcorporate.expresso.core.controller.Output;
078: import com.jcorporate.expresso.core.controller.State;
079: import com.jcorporate.expresso.core.controller.Transition;
080: import com.jcorporate.expresso.core.db.DBException;
081: import com.jcorporate.expresso.core.dbobj.Schema;
082: import com.jcorporate.expresso.core.dbobj.SecuredDBObject;
083: import com.jcorporate.expresso.core.dbobj.ValidValue;
084: import com.jcorporate.expresso.core.misc.ConfigManager;
085: import com.jcorporate.expresso.services.controller.Registration;
086: import com.jcorporate.expresso.services.dbobj.SchemaList;
087: import junit.framework.AssertionFailedError;
088: import junit.framework.Test;
089: import junit.framework.TestFailure;
090: import junit.framework.TestListener;
091: import junit.framework.TestResult;
092: import junit.framework.TestSuite;
093: import junit.runner.ReloadingTestSuiteLoader;
094: import junit.runner.StandardTestSuiteLoader;
095: import junit.runner.TestSuiteLoader;
096: import org.apache.log4j.Logger;
097:
098: import java.io.File;
099: import java.io.FileInputStream;
100: import java.io.IOException;
101: import java.io.InputStream;
102: import java.lang.reflect.Method;
103: import java.text.NumberFormat;
104: import java.util.Enumeration;
105: import java.util.Iterator;
106: import java.util.Properties;
107: import java.util.Vector;
108:
109: /**
110: * TestController is a controller that can access and run
111: * JUnit unit tests, but from within an Expresso environment (e.g.
112: * with the DBConnection pool, Cache, and other Expresso items
113: * available, and from a servlet (such as ControllerServlet).
114: * This allows tests that require the servlet environment or Expresso
115: * components to be executed.
116: *
117: * @author Michael Nash
118: */
119: public class TestController extends DBController implements
120: TestListener {
121: static final String SUITE_METHODNAME = "suite";
122: static Properties fPreferences;
123: static int fMaxMessage = 200;
124: protected TestSuiteLoader fTestLoader;
125: private static Logger log = Logger.getLogger(TestController.class);
126:
127: /**
128: * Default constructor
129: */
130: public TestController() {
131: super ();
132: System.setProperty("junit.argv.configDir", ConfigManager
133: .getConfigDir());
134: System.setProperty("junit.argv.webAppDir", ConfigManager
135: .getWebAppDir());
136: fTestLoader = new StandardTestSuiteLoader();
137:
138: State prompt = new State("prompt", "Prompt for Test to Run");
139: addState(prompt);
140: setInitialState("prompt");
141:
142: State runTests = new State("runTests", "Run Tests");
143: runTests.addRequiredParameter("testName");
144: addState(runTests);
145:
146: State runAllTests = new State("runAllTests", "Run All Tests");
147: runAllTests.addRequiredParameter("SchemaClass");
148: addState(runAllTests);
149:
150: addState(new State("transition2FormTest",
151: "test a transition to a state which requires a form"));
152: addState(new State("transitionTest", "test a transition"));
153: addState(new State("promptTest",
154: "prompt for transitionFromFormTest"));
155: addState(new State("transitionFromFormTest",
156: "test a transition from a form"));
157: this
158: .setSchema(com.jcorporate.expresso.core.ExpressoSchema.class);
159: } /* TestController() */
160:
161: /**
162: * Standard method to select the appropriate next state as the
163: * controller moves from state to state.
164: *
165: * @param newState
166: */
167: public ControllerResponse newState(String newState,
168: ControllerRequest params) throws ControllerException,
169: NonHandleableException {
170: ControllerResponse myResponse = super
171: .newState(newState, params);
172:
173: if (newState.equals("runTests")) {
174: runTestsState(myResponse, params);
175: } else if (newState.equals("runAllTests")) {
176: runAllTestsState(myResponse, params);
177: } else if (newState.equals("prompt")) {
178: promptState(myResponse, params);
179: }
180:
181: return myResponse;
182: } /* newState(String) */
183:
184: /**
185: * @param test
186: * @param t
187: */
188: public synchronized void addError(Test test, Throwable t) {
189: log.info("A test error has occurred");
190: log.error(t);
191: } /* addError(Test, Throwable) */
192:
193: /**
194: * @param test
195: * @param t
196: */
197: public synchronized void addFailure(Test test, Throwable t) {
198: log.info("A test failure has occurred");
199: log.error(t);
200: } /* addFailure(Test, Throwable) */
201:
202: /**
203: * Creates the TestResult to be used for the test run.
204: *
205: * @return
206: */
207: protected TestResult createTestResult() {
208: return new TestResult();
209: } /* createTestResult() */
210:
211: /**
212: * @param suite
213: * @param wait
214: * @return
215: */
216: protected synchronized TestResult doRun(Test suite, boolean wait) {
217: try {
218: TestResult result = createTestResult();
219: result.addListener(this );
220:
221: long startTime = System.currentTimeMillis();
222: suite.run(result);
223:
224: long endTime = System.currentTimeMillis();
225: long runTime = endTime - startTime;
226: log.info("Time: " + elapsedTimeAsString(runTime));
227: print(result);
228:
229: return result;
230: } catch (Exception ee) {
231: log.error(ee);
232: }
233:
234: return null;
235: } /* doRun(Test, boolean) */
236:
237: /**
238: * @param test
239: */
240: public void endTest(Test test) {
241: } /* endTest(Test) */
242:
243: /**
244: * Added since JUnit 3.7
245: */
246: public void addFailure(Test test, AssertionFailedError t) {
247: log.info("A test failure has occurred");
248: log.info(t);
249: }
250:
251: /**
252: * Actually execute the selected test(s)
253: */
254: private synchronized void runTestsState(
255: ControllerResponse myResponse, ControllerRequest params)
256: throws ControllerException {
257: long startTime = System.currentTimeMillis();
258: TestController aTestRunner = new TestController();
259:
260: try {
261: TestResult r = aTestRunner.start(null); /* testToRun */
262:
263: if (!r.wasSuccessful()) {
264: myResponse.addOutput(new Output("Tests Successful"));
265: }
266:
267: myResponse
268: .addOutput(new Output("One or more tests failed"));
269: } catch (Exception e) {
270: log.error(e);
271: throw new ControllerException(e);
272: }
273:
274: long endTime = System.currentTimeMillis();
275: long runTime = endTime - startTime;
276: myResponse.addOutput(new Output("Total Elapsed Time " + runTime
277: + " milliseconds"));
278: } /* runTestsState(); */
279:
280: /**
281: * Execute all available tests for the specified schema class
282: */
283: private synchronized void runAllTestsState(
284: ControllerResponse myResponse, ControllerRequest params)
285: throws ControllerException {
286: Schema s = getSchemaObject(params);
287: myResponse.addOutput(new Output("Running all tests in schema "
288: + s.getClass().getName()));
289:
290: long startTime = System.currentTimeMillis();
291: int testCount = 0;
292: int succeedCount = 0;
293: int failedCount = 0;
294: Test t = null;
295:
296: for (Enumeration et2 = s.getTests(); et2.hasMoreElements();) {
297: t = (Test) et2.nextElement();
298: testCount++;
299:
300: TestController aTestRunner = new TestController();
301:
302: try {
303: TestResult r = aTestRunner
304: .start(t.getClass().getName());
305:
306: if (r.wasSuccessful()) {
307: myResponse.addOutput(new Output("Test "
308: + t.getClass().getName() + " Successful"));
309: succeedCount++;
310: } else {
311: myResponse.addOutput(new Output("Test "
312: + t.getClass().getName()
313: + " failed - see the log for details"));
314: failedCount++;
315: }
316: } catch (Exception e) {
317: log.error(e);
318: throw new ControllerException(e);
319: }
320: } /* for each test */
321:
322: long endTime = System.currentTimeMillis();
323: long runTime = endTime - startTime;
324: myResponse.addOutput(new Output("All Tests Completed"));
325: myResponse.addOutput(new Output("Total Elapsed Time " + runTime
326: + " milliseconds"));
327: myResponse.addOutput(new Output("" + testCount + " tests run, "
328: + succeedCount + " succeeded, " + failedCount
329: + " failed"));
330: } /* runAllTestsState() */
331:
332: /**
333: * Instantiate & return the schema class given in the current parameter
334: *
335: * @return A Schema object instantiated from the class named by the
336: * 'SchemaClass' parameter
337: */
338: private Schema getSchemaObject(ControllerRequest params)
339: throws ControllerException {
340: Schema mySchema;
341: String className = params.getParameter("SchemaClass");
342:
343: if (className == null) {
344: throw new ControllerException("No parameter 'SchemaClass',"
345: + " can't read current schema");
346: }
347: try {
348: mySchema = (Schema) Class.forName(
349: params.getParameter("SchemaClass")).newInstance();
350: } catch (IllegalAccessException ie) {
351: throw new ControllerException("Illegal Access "
352: + "Exception loading Schema class "
353: + params.getParameter("SchemaClass"), ie);
354: } catch (InstantiationException ie) {
355: throw new ControllerException("Can't instantiate "
356: + "Schema class "
357: + params.getParameter("SchemaClass"), ie);
358: } catch (ClassNotFoundException se) {
359: throw new ControllerException("Can't find a Schema "
360: + "class called "
361: + params.getParameter("SchemaClass"), se);
362: } catch (Exception eo) {
363: log.error(eo);
364: throw new ControllerException("Exception loading "
365: + "Schema " + params.getParameter("SchemaClass")
366: + "- see detailed message in server log", eo);
367: }
368:
369: return mySchema;
370: } /* getSchemaObject() */
371:
372: /**
373: * Prints failures to the log
374: *
375: * @param result
376: */
377: public synchronized void print(TestResult result) {
378: printHeader(result);
379: printErrors(result);
380: printFailures(result);
381: } /* print(TestResult) */
382:
383: /**
384: * Prints the errors to the log
385: *
386: * @param result
387: */
388: public void printErrors(TestResult result) {
389: if (result.errorCount() != 0) {
390: if (result.errorCount() == 1) {
391: log
392: .info("There was " + result.errorCount()
393: + " error:");
394: } else {
395: log.info("There were " + result.errorCount()
396: + " errors:");
397: }
398:
399: int i = 1;
400:
401: for (Enumeration e = result.errors(); e.hasMoreElements(); i++) {
402: TestFailure failure = (TestFailure) e.nextElement();
403: log.info(i + ") " + failure.failedTest());
404: log.info(failure.thrownException());
405: }
406: }
407: } /* printErrors(TestResult) */
408:
409: /**
410: * Prints failures to the log
411: *
412: * @param result
413: */
414: public void printFailures(TestResult result) {
415: if (result.failureCount() != 0) {
416: if (result.failureCount() == 1) {
417: log.info("There was " + result.failureCount()
418: + " failure:");
419: } else {
420: log.info("There were " + result.failureCount()
421: + " failures:");
422: }
423:
424: int i = 1;
425:
426: for (Enumeration e = result.failures(); e.hasMoreElements(); i++) {
427: TestFailure failure = (TestFailure) e.nextElement();
428: log.info(i + ") " + failure.failedTest());
429:
430: Throwable t = failure.thrownException();
431:
432: if (t.getMessage() != null) {
433: log.info(" \"" + truncate(t.getMessage()) + "\"");
434: } else {
435: log.info(failure.thrownException());
436: }
437: }
438: }
439: } /* printFailures(TestResult) */
440:
441: /**
442: * Prints the header of the report
443: *
444: * @param result
445: */
446: public void printHeader(TestResult result) {
447: if (result.wasSuccessful()) {
448: log.info("OK");
449: log.info(" (" + result.runCount() + " tests)");
450: } else {
451: log.info("FAILURES!!!");
452: log.info("Test Results:");
453: log.info("Run: " + result.runCount() + " Failures: "
454: + result.failureCount() + " Errors: "
455: + result.errorCount());
456: }
457: } /* printHeader(TestResult) */
458:
459: /**
460: * Runs a suite extracted from a TestCase subclass.
461: *
462: * @param testClass
463: */
464: static public void run(Class testClass) {
465: run(new TestSuite(testClass));
466: } /* run(Class) */
467:
468: /**
469: * Runs a single test and collects its results.
470: * This method can be used to start a test run
471: * from your program.
472: * <pre>
473: * public static void main (String[] args) {
474: * test.textui.TestRunner.run(suite());
475: * }
476: * </pre>
477: *
478: * @param suite
479: */
480: static public void run(Test suite) {
481: TestController aTestRunner = new TestController();
482: aTestRunner.doRun(suite, false);
483: } /* run(Test) */
484:
485: /**
486: * Starts a test run. Analyzes the command line arguments
487: * and runs the given test suite.
488: *
489: * @param testName
490: * @return
491: */
492: protected synchronized TestResult start(String testName)
493: throws Exception {
494: boolean wait = false;
495:
496: try {
497: Test suite = getTest(testName);
498:
499: return doRun(suite, wait);
500: } catch (Exception e) {
501: throw new Exception("Could not create and run test suite: "
502: + e);
503: }
504: } /* start(String) */
505:
506: /**
507: * @param message
508: */
509: protected void runFailed(String message) {
510: log.info(message);
511: } /* runFailed(String) */
512:
513: /**
514: * @param test
515: */
516: public synchronized void startTest(Test test) {
517: log.info("Test Started");
518: } /* startTest(Test) */
519:
520: /**
521: * Returns the Test corresponding to the given suite. This is
522: * a template method, subclasses override runFailed(), clearStatus().
523: *
524: * @param suiteClassName
525: * @return
526: */
527: public Test getTest(String suiteClassName) {
528: if (suiteClassName.length() <= 0) {
529: clearStatus();
530:
531: return null;
532: }
533:
534: Class testClass = null;
535:
536: try {
537: testClass = loadSuiteClass(suiteClassName);
538: } catch (NoClassDefFoundError e) {
539: runFailed("Class definition \"" + suiteClassName
540: + "\" not found");
541:
542: return null;
543: } catch (Exception e) {
544: runFailed("Class \"" + suiteClassName + "\" not found");
545:
546: return null;
547: }
548:
549: Method suiteMethod = null;
550:
551: try {
552: suiteMethod = testClass.getMethod(SUITE_METHODNAME,
553: new Class[0]);
554: } catch (Exception e) {
555:
556: // try to extract a test suite automatically
557: clearStatus();
558:
559: return new TestSuite(testClass);
560: }
561:
562: Test test = null;
563:
564: try {
565: test = (Test) suiteMethod.invoke(null,
566: (Object[]) new Class[0]); // static method
567:
568: if (test == null) {
569: return test;
570: }
571: } catch (Exception e) {
572: runFailed("Could not invoke the suite() method");
573:
574: return null;
575: }
576:
577: clearStatus();
578:
579: return test;
580: } /* getTest(String) */
581:
582: /**
583: * Returns the formatted string of the elapsed time.
584: *
585: * @param runTime
586: * @return
587: */
588: public String elapsedTimeAsString(long runTime) {
589: return NumberFormat.getInstance().format(
590: (double) runTime / 1000);
591: } /* elaspedTimeAsString(long) */
592:
593: /**
594: * @param className
595: * @return
596: */
597: public String extractClassName(String className) {
598: if (className.startsWith("Default package for")) {
599: return className.substring(className.lastIndexOf(".") + 1);
600: }
601:
602: return className;
603: } /* extractClassName(String) */
604:
605: /**
606: * Truncates a String to the maximum length.
607: *
608: * @param s
609: * @return
610: */
611: public static String truncate(String s) {
612: if (s.length() > fMaxMessage) {
613: s = s.substring(0, fMaxMessage) + "...";
614: }
615:
616: return s;
617: } /* truncate(String) */
618:
619: /**
620: * Returns the loaded Class for a suite name.
621: *
622: * @param suiteClassName
623: * @return
624: */
625: protected Class loadSuiteClass(String suiteClassName)
626: throws ClassNotFoundException {
627: return fTestLoader.load(suiteClassName);
628: } /* loadSuiteClass(String) */
629:
630: /**
631: * Clears the status message.
632: */
633: protected void clearStatus() { // Belongs in the GUI TestRunner class
634: } /* clearStatus() */
635:
636: /**
637: * Returns the loader to be used.
638: *
639: * @return
640: */
641: public static TestSuiteLoader getLoader() {
642: if (getPreference("loading").equals("true") && !inVAJava()) {
643: return new ReloadingTestSuiteLoader();
644: }
645:
646: return new StandardTestSuiteLoader();
647: } /* getLoader() */
648:
649: /**
650: * @return
651: */
652: private static File getPreferencesFile() {
653: String home = System.getProperty("user.home");
654:
655: return new File(home, "junit.properties");
656: } /* getPreferencesFile() */
657:
658: /**
659: *
660: */
661: private static void readPreferences() {
662: InputStream is = null;
663:
664: try {
665: is = new FileInputStream(getPreferencesFile());
666: fPreferences = new Properties(fPreferences);
667: fPreferences.load(is);
668: } catch (IOException e) {
669: try {
670: if (is != null) {
671: is.close();
672: }
673: } catch (IOException e1) {
674: }
675: }
676: } /* readPreferences() */
677:
678: /**
679: * @param key
680: * @return
681: */
682: private static String getPreference(String key) {
683: return fPreferences.getProperty(key);
684: } /* getPreferences(String) */
685:
686: /**
687: * @param key
688: * @param dflt
689: * @return
690: */
691: private static int getPreference(String key, int dflt) {
692: String value = getPreference(key);
693: int intValue = dflt;
694:
695: if (value == null) {
696: return intValue;
697: }
698: try {
699: intValue = Integer.parseInt(value);
700: } catch (NumberFormatException ne) {
701: }
702:
703: return intValue;
704: } /* getPreferences(String, int) */
705:
706: /**
707: * @return
708: */
709: public static boolean inVAJava() {
710: try {
711: Class.forName("com.ibm.uvm.tools.DebugSupport");
712: } catch (Exception e) {
713: return false;
714: }
715:
716: return true;
717: }
718:
719: {
720: fPreferences = new Properties();
721: fPreferences.setProperty("loading", "true");
722: readPreferences();
723: fMaxMessage = getPreference("maxmessage", fMaxMessage);
724: }
725:
726: public String getTitle() {
727: return ("Run Unit Tests");
728: }
729:
730: private void promptState(ControllerResponse myResponse,
731: ControllerRequest params) throws ControllerException {
732: try {
733: Input chooseSchema = new Input();
734: chooseSchema.setLabel("Choose Schema");
735: chooseSchema.setName("SchemaClass");
736:
737: Vector v2 = new Vector(2);
738: v2.addElement(new ValidValue("com.jcorporate.expresso."
739: + "core.ExpressoSchema", "General"));
740:
741: SchemaList sl = new SchemaList(
742: SecuredDBObject.SYSTEM_ACCOUNT);
743: sl.setDataContext(params.getDataContext());
744:
745: SchemaList oneSchema = null;
746:
747: for (Iterator e = sl.searchAndRetrieveList("Descrip")
748: .iterator(); e.hasNext();) {
749: oneSchema = (SchemaList) e.next();
750: v2.addElement(new ValidValue(oneSchema
751: .getField("SchemaClass"), oneSchema
752: .getField("Descrip")));
753: }
754:
755: chooseSchema.setValidValues(v2);
756: myResponse.addInput(chooseSchema);
757:
758: /* now the actions */
759:
760: /* Action selTest = new Action("Select Test(s)", getClass().getName());
761:
762: selTest.setName("selTest");
763:
764: selTest.addParam(STATE_PARAM_KEY, "selTest");
765:
766: addAction(selTest); */
767: Transition runAllTests = new Transition("Run All Tests",
768: getClass().getName());
769: runAllTests.setName("runAllTests");
770: runAllTests.addParam(STATE_PARAM_KEY, "runAllTests");
771: myResponse.addTransition(runAllTests);
772: } catch (DBException de) {
773: throw new ControllerException(de);
774: }
775: }
776:
777: /**
778: * test a transition to a controller/state
779: * which requires a form
780: */
781: protected void runTransition2FormTestState(
782: ControllerRequest request, ControllerResponse response)
783: throws ControllerException, NonHandleableException {
784: Transition trans = new Transition();
785: trans.setControllerObject(Registration.class);
786: trans.setState("promptSelfRegister");
787: trans.addParam("dbContext", "default");
788: trans.transition(request, response);
789: }
790:
791: /**
792: * test a transition to a controller/state
793: * note that the ControllerSecurityMatrix output uses the default layout,
794: * so the title at the top of that page will show this test controller.
795: */
796: protected void runTransitionTestState(ControllerRequest request,
797: ControllerResponse response) throws ControllerException,
798: NonHandleableException {
799: Transition trans = new Transition();
800: trans.setControllerObject(Download.class);
801: trans.setState("list");
802: trans.transition(request, response);
803: }
804:
805: /**
806: * test a transition to a controller/state
807: * which requires a form
808: */
809: protected void runPromptTestState(ControllerRequest request,
810: ControllerResponse response) throws ControllerException,
811: NonHandleableException {
812: Input input = new Input("demoprompt", "demoprompt");
813: //input.setType("textbox");
814: response.addInput(input);
815: Transition trans = new Transition("transitionFromFormTest",
816: this );
817: response.addTransition(trans);
818: }
819:
820: /**
821: * test a transition from a controller/state
822: * which uses a form to one that does not use a form
823: */
824: protected void runTransitionFromFormTestState(
825: ControllerRequest request, ControllerResponse response)
826: throws ControllerException, NonHandleableException {
827: Transition trans = new Transition();
828: trans.setControllerObject(Download.class);
829: trans.setState("list");
830: trans.transition(request, response);
831: }
832:
833: } /* TestController */
|