Version: current

      1 <?php
      2 /**
      3  * Controller that executes QUnit tests via jQuery.
      4  * Finds all htm/html files located in <yourmodule>/javascript/tests
      5  * and includes them as iFrames.
      6  *
      7  * To create your own tests, please use this template:
      8  * <code>
      9  * <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
     10  * <html>
     11  * <head>
     12  *  <script src="http://code.jquery.com/jquery-latest.js"></script>
     13  *  <link rel="stylesheet" href="http://dev.jquery.com/view/trunk/qunit/testsuite.css" type="text/css" media="screen" />
     14  *  <script>
     15  *  $(document).ready(function(){
     16  *      test("test my feature", function() {
     17  *          ok('mytest');
     18  *      });
     19  *  });
     20  *   </script>
     21  * </head>
     22  * <body>
     23  * <script type="text/javascript" src="http://jqueryjs.googlecode.com/svn/trunk/qunit/testrunner.js"></script>
     24  *  <h1>My Test Name</h1>
     25  *  <h2 id="banner"></h2>
     26  *  <h2 id="userAgent"></h2>
     27  *  <ol id="tests"></ol>
     28  *  <div id="main"></div>
     29  * </body>
     30  * </html>
     31  * </code>
     32  *
     33  * @package sapphire
     34  * @subpackage testing
     35  */
     36 class JSTestRunner extends Controller {
     37     /** @ignore */
     38     private static $default_reporter;
     39
     40     static $url_handlers = array(
     41         '' => 'browse',
     42         '$TestCase' => 'only',
     43     );
     44
     45     /**
     46      * Override the default reporter with a custom configured subclass.
     47      *
     48      * @param string $reporter
     49      */
     50     static function set_reporter($reporter) {
     51         if (is_string($reporter)) $reporter = new $reporter;
     52         self::$default_reporter = $reporter;
     53     }
     54
     55     function init() {
     56         parent::init();
     57
     58         if(Director::is_cli()) {
     59             echo "Error: JSTestRunner cannot be run in CLI mode\n";
     60             die();
     61         }
     62
     63         if (!self::$default_reporter) self::set_reporter('DebugView');
     64     }
     65
     66     public function Link() {
     67         return Controller::join_links(Director::absoluteBaseURL(), 'dev/jstests/');
     68     }
     69
     70     /**
     71      * Run all test classes
     72      */
     73     function all() {
     74         $this->runTests(array_keys($this->getAllTestFiles()));
     75     }
     76
     77     /**
     78      * Browse all enabled test cases in the environment
     79      */
     80     function browse() {
     81         self::$default_reporter->writeHeader();
     82         echo '<div class="info">';
     83         echo '<h1>Available Tests</h1>';
     84         echo '</div>';
     85         echo '<div class="trace">';
     86         $tests = $this->getAllTestFiles();
     87         echo "<h3><a href=\"" . $this->Link() . "all\">Run all " . count($tests) . " tests</a></h3>";
     88         echo "<hr />";
     89         foreach ($tests as $testName => $testFilePath) {
     90             echo "<h3><a href=\"" . $this->Link() . "$testName\">Run $testName</a></h3>";
     91         }
     92         echo '</div>';
     93         self::$default_reporter->writeFooter();
     94     }
     95
     96     /**
     97      * Run only a single test class
     98      */
     99     function only($request) {
    100         $test = $request->param('TestCase');
    101
    102         if ($test == 'all') {
    103             $this->all();
    104         } else {
    105             $allTests = $this->getAllTestFiles();
    106             if(!array_key_exists($test, $allTests)) {
    107                 user_error("TestRunner::only(): Invalid TestCase '$className', cannot find matching class", E_USER_ERROR);
    108             }
    109
    110             $this->runTests(array($test));
    111         }
    112     }
    113
    114     function runTests($tests) {
    115         $this->setUp();
    116
    117         self::$default_reporter->writeHeader("Sapphire JavaScript Test Runner");
    118         self::$default_reporter->writeInfo("All Tests", "Running test cases: " . implode(", ", $tests));
    119
    120         foreach($tests as $test) {
    121             // @todo Integrate output in DebugView
    122             $testUrl = $this->urlForTestCase($test);
    123             if(!$testUrl) user_error('JSTestRunner::runTests(): Test ' . $test . ' not found', E_USER_ERROR);
    124             $absTestUrl = Director::absoluteBaseURL() . $testUrl;
    125
    126             echo '<iframe src="' . $absTestUrl . '" width="800" height="300"></iframe>';
    127         }
    128
    129         $this->tearDown();
    130     }
    131
    132     function setUp() {
    133     }
    134
    135     function tearDown() {
    136     }
    137
    138     protected function getAllTestFiles() {
    139         $testFiles = array();
    140
    141         $baseDir = Director::baseFolder();
    142         $modules = scandir($baseDir);
    143         foreach($modules as $moduleFileOrFolder) {
    144             if(
    145                 $moduleFileOrFolder[0] == '.'
    146                 || !@is_dir("$baseDir/$moduleFileOrFolder")
    147                 || !file_exists("$baseDir/$moduleFileOrFolder/_config.php")
    148             ) {
    149                 continue;
    150             }
    151
    152             $testDir = "$baseDir/$moduleFileOrFolder/tests/javascript";
    153             if(@is_dir($testDir)) {
    154                 $tests = scandir($testDir);
    155                 foreach($tests as $testFile) {
    156                     $testFileExt = pathinfo("$testDir/$testFile", PATHINFO_EXTENSION);
    157                     if(!in_array(strtolower($testFileExt),array('htm','html'))) continue;
    158                     $testFileNameWithoutExt = substr($testFile, 0,-strlen($testFileExt)-1);
    159                     $testUrl = Director::makeRelative("$testDir/$testFile");
    160                     $testUrl = substr($testUrl, 1);
    161                     // @todo Limit to html extension with "Test" suffix
    162                     $testFiles[$testFileNameWithoutExt] = $testUrl;
    163                 }
    164             }
    165         }
    166
    167         return $testFiles;
    168     }
    169
    170     /**
    171      * Returns the URL for a test case file.
    172      *
    173      * @return string
    174      */
    175     protected function urlForTestCase($testName) {
    176         $allTests = $this->getAllTestFiles();
    177         return (array_key_exists($testName, $allTests)) ? $allTests[$testName] : false;
    178     }
    179 }
    180

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -