Add jstd-scenario-adapter so we can run e2e tests with JsTD
authorVojta Jina <vojta.jina@gmail.com>
Mon, 13 Jun 2011 16:31:46 +0000 (18:31 +0200)
committerVojta Jina <vojta.jina@gmail.com>
Mon, 13 Jun 2011 16:31:46 +0000 (18:31 +0200)
Added basic configuration, so all you need to run e2e tests:
1/ start web server in project root
>> ./scripts/web-server.js

2/ start JsTD server
>> ./scripts/e2e-test-server.sh

3/ capture some browser
navigate to http://localhost:9877/capture

4/ run the tests
>> ./scripts/e2e-test.sh

config/jsTestDriver-scenario.conf [new file with mode: 0644]
config/jstd-scenario-adapter-config.js [new file with mode: 0644]
scripts/e2e-test-server.bat [new file with mode: 0644]
scripts/e2e-test-server.sh [new file with mode: 0755]
scripts/e2e-test.bat [new file with mode: 0644]
scripts/e2e-test.sh [new file with mode: 0755]
test/lib/angular/jstd-scenario-adapter.js [new file with mode: 0644]

diff --git a/config/jsTestDriver-scenario.conf b/config/jsTestDriver-scenario.conf
new file mode 100644 (file)
index 0000000..3ebe650
--- /dev/null
@@ -0,0 +1,10 @@
+server: http://localhost:9877
+
+load:
+  - test/lib/angular/angular-scenario.js
+  - config/jstd-scenario-adapter-config.js
+  - test/lib/angular/jstd-scenario-adapter.js
+  - test/e2e/scenarios.js
+
+proxy:
+ - {matcher: "*", server: "http://localhost:8000"}
diff --git a/config/jstd-scenario-adapter-config.js b/config/jstd-scenario-adapter-config.js
new file mode 100644 (file)
index 0000000..21eebc4
--- /dev/null
@@ -0,0 +1,6 @@
+/**\r
+ * Configuration for jstd scenario adapter 
+ */
+var jstdScenarioAdapter = {
+  relativeUrlPrefix: '/test/e2e/'
+};
diff --git a/scripts/e2e-test-server.bat b/scripts/e2e-test-server.bat
new file mode 100644 (file)
index 0000000..f857b0d
--- /dev/null
@@ -0,0 +1,18 @@
+@echo off
+
+REM Windows script for starting JSTD server
+REM
+REM Requirements:
+REM - Java (http://www.java.com)
+
+set BASE_DIR=%~dp0
+set PORT=9877
+
+echo "Starting JsTestDriver Server (http://code.google.com/p/js-test-driver/)"
+echo "Please open the following url and capture one or more browsers:"
+echo "http://localhost:%PORT%"
+java -jar "%BASE_DIR%\..\test\lib\jstestdriver\JsTestDriver.jar" ^
+     --port %PORT% ^
+     --browserTimeout 20000 ^
+     --config "%BASE_DIR%\..\config\jsTestDriver-scenario.conf" ^
+     --basePath "%BASE_DIR%\.."
diff --git a/scripts/e2e-test-server.sh b/scripts/e2e-test-server.sh
new file mode 100755 (executable)
index 0000000..5a4e04c
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+BASE_DIR=`dirname $0`
+PORT=9877
+
+echo "Starting JsTestDriver Server (http://code.google.com/p/js-test-driver/)"
+echo "Please open the following url and capture one or more browsers:"
+echo "http://localhost:$PORT"
+
+java -jar "$BASE_DIR/../test/lib/jstestdriver/JsTestDriver.jar" \
+     --port $PORT \
+     --browserTimeout 20000 \
+     --config "$BASE_DIR/../config/jsTestDriver-scenario.conf" \
+     --basePath "$BASE_DIR/.."
diff --git a/scripts/e2e-test.bat b/scripts/e2e-test.bat
new file mode 100644 (file)
index 0000000..f630363
--- /dev/null
@@ -0,0 +1,13 @@
+@echo off
+
+REM Windows script for running e2e tests
+REM You have to run server and capture some browser first
+REM
+REM Requirements:
+REM - Java (http://www.java.com)
+
+set BASE_DIR=%~dp0
+java -jar "%BASE_DIR%\..\test\lib\jstestdriver\JsTestDriver.jar" ^
+     --config "%BASE_DIR%\..\config\jsTestDriver-scenario.conf" ^
+     --basePath "%BASE_DIR%\.." ^
+     --tests all --reset
diff --git a/scripts/e2e-test.sh b/scripts/e2e-test.sh
new file mode 100755 (executable)
index 0000000..41211f7
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+BASE_DIR=`dirname $0`
+
+java -jar "$BASE_DIR/../test/lib/jstestdriver/JsTestDriver.jar" \
+     --config "$BASE_DIR/../config/jsTestDriver-scenario.conf" \
+     --basePath "$BASE_DIR/.." \
+     --tests all --reset
diff --git a/test/lib/angular/jstd-scenario-adapter.js b/test/lib/angular/jstd-scenario-adapter.js
new file mode 100644 (file)
index 0000000..f0aab2c
--- /dev/null
@@ -0,0 +1,201 @@
+/**
+ * The MIT License
+ *
+ * Copyright (c) 2010 Adam Abrons and Misko Hevery http://getangular.com
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+(function(window) {
+/**
+ * JSTestDriver adapter for angular scenario tests
+ *
+ * Example of jsTestDriver.conf for running scenario tests with JSTD:
+  <pre>
+    server: http://localhost:9877
+
+    load:
+      - lib/angular-scenario.js
+      - lib/jstd-scenario-adapter-config.js
+      - lib/jstd-scenario-adapter.js
+      # your test files go here #
+
+    proxy:
+     - {matcher: "/your-prefix/*", server: "http://localhost:8000/"}
+  </pre>
+ *
+ * For more information on how to configure jstd proxy, see {@link http://code.google.com/p/js-test-driver/wiki/Proxy}
+ * Note the order of files - it's important !
+ *
+ * Example of jstd-scenario-adapter-config.js
+  <pre>
+    var jstdScenarioAdapter = {
+      relativeUrlPrefix: '/your-prefix/'
+    };
+  </pre>
+ *
+ * Whenever you use <code>browser().navigateTo('relativeUrl')</code> in your scenario test, the relativeUrlPrefix will be prepended.
+ * You have to configure this to work together with JSTD proxy.
+ *
+ * Let's assume you are using the above configuration (jsTestDriver.conf and jstd-scenario-adapter-config.js):
+ * Now, when you call <code>browser().navigateTo('index.html')</code> in your scenario test, the browser will open /your-prefix/index.html.
+ * That matches the proxy, so JSTD will proxy this request to http://localhost:8000/index.html.
+ */
+
+/**
+ * Custom type of test case
+ *
+ * @const
+ * @see jstestdriver.TestCaseInfo
+ */
+var SCENARIO_TYPE = 'scenario';
+
+/**
+ * Plugin for JSTestDriver
+ * Connection point between scenario's jstd output and jstestdriver.
+ *
+ * @see jstestdriver.PluginRegistrar
+ */
+function JstdPlugin() {
+  var nop = function() {};
+
+  this.reportResult = nop;
+  this.reportEnd = nop;
+  this.runScenario = nop;
+
+  this.name = 'Angular Scenario Adapter';
+
+  /**
+   * Called for each JSTD TestCase
+   *
+   * Handles only SCENARIO_TYPE test cases. There should be only one fake TestCase.
+   * Runs all scenario tests (under one fake TestCase) and report all results to JSTD.
+   *
+   * @param {jstestdriver.TestRunConfiguration} configuration
+   * @param {Function} onTestDone
+   * @param {Function} onAllTestsComplete
+   * @returns {boolean} True if this type of test is handled by this plugin, false otherwise
+   */
+  this.runTestConfiguration = function(configuration, onTestDone, onAllTestsComplete) {
+    if (configuration.getTestCaseInfo().getType() != SCENARIO_TYPE) return false;
+
+    this.reportResult = onTestDone;
+    this.reportEnd = onAllTestsComplete;
+    this.runScenario();
+
+    return true;
+  };
+
+  this.getTestRunsConfigurationFor = function(testCaseInfos, expressions, testRunsConfiguration) {
+    testRunsConfiguration.push(
+        new jstestdriver.TestRunConfiguration(
+            new jstestdriver.TestCaseInfo(
+                'Angular Scenario Tests', function() {}, SCENARIO_TYPE), []));
+
+    return true;
+  };
+}
+
+/**
+ * Singleton instance of the plugin
+ * Accessed using closure by:
+ *  - jstd output (reports to this plugin)
+ *  - initScenarioAdapter (register the plugin to jstd)
+ */
+var plugin = new JstdPlugin();
+
+/**
+ * Initialise scenario jstd-adapter
+ * (only if jstestdriver is defined)
+ *
+ * @param {Object} jstestdriver Undefined when run from browser (without jstd)
+ * @param {Function} initScenarioAndRun Function that inits scenario and runs all the tests
+ * @param {Object=} config Configuration object, supported properties:
+ *  - relativeUrlPrefix: prefix for all relative links when navigateTo()
+ */
+function initScenarioAdapter(jstestdriver, initScenarioAndRun, config) {
+  if (jstestdriver) {
+    // create and register ScenarioPlugin
+    jstestdriver.pluginRegistrar.register(plugin);
+    plugin.runScenario = initScenarioAndRun;
+
+    /**
+     * HACK (angular.scenario.Application.navigateTo)
+     *
+     * We need to navigate to relative urls when running from browser (without JSTD),
+     * because we want to allow running scenario tests without creating its own virtual host.
+     * For example: http://angular.local/build/docs/docs-scenario.html
+     *
+     * On the other hand, when running with JSTD, we need to navigate to absolute urls,
+     * because of JSTD proxy. (proxy, because of same domain policy)
+     *
+     * So this hack is applied only if running with JSTD and change all relative urls to absolute.
+     */
+    var appProto = angular.scenario.Application.prototype,
+        navigateTo = appProto.navigateTo,
+        relativeUrlPrefix = config && config.relativeUrlPrefix || '/';
+
+    appProto.navigateTo = function(url, loadFn, errorFn) {
+      if (url.charAt(0) != '/' && url.charAt(0) != '#' &&
+          url != 'about:blank' && !url.match(/^https?/)) {
+        url = relativeUrlPrefix + url;
+      }
+
+      return navigateTo.call(this, url, loadFn, errorFn);
+    };
+  }
+}
+
+/**
+ * Builds proper TestResult object from given model spec
+ *
+ * TODO(vojta) report error details
+ *
+ * @param {angular.scenario.ObjectModel.Spec} spec
+ * @returns {jstestdriver.TestResult}
+ */
+function createTestResultFromSpec(spec) {
+  var map = {
+    success: 'PASSED',
+    error:   'ERROR',
+    failure: 'FAILED'
+  };
+
+  return new jstestdriver.TestResult(
+    spec.fullDefinitionName,
+    spec.name,
+    jstestdriver.TestResult.RESULT[map[spec.status]],
+    spec.error || '',
+    spec.line || '',
+    spec.duration);
+}
+
+/**
+ * Generates JSTD output (jstestdriver.TestResult)
+ */
+angular.scenario.output('jstd', function(context, runner, model) {
+  model.on('SpecEnd', function(spec) {
+    plugin.reportResult(createTestResultFromSpec(spec));
+  });
+
+  model.on('RunnerEnd', function() {
+    plugin.reportEnd();
+  });
+});
+initScenarioAdapter(window.jstestdriver, angular.scenario.setUpAndRun, window.jstdScenarioAdapter);
+})(window);