Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

extract from iTest2

  • Loading branch information...
commit 61f5f88e54f163500584dc63fa3952486451d458 0 parents
authored

Showing 49 changed files with 3,132 additions and 0 deletions. Show diff stats Hide diff stats

  1. 16  ChangeLog.txt
  2. 23  License.txt
  3. BIN  ant-jars/js-1.6R7.jar
  4. 6  build.base.properties
  5. 185  build.xml
  6. 3  src/chrome.manifest
  7. 64  src/content/UnitTestUtils.js
  8. 62  src/content/WTREditorCtxMenu.js
  9. 57  src/content/WTRStep.js
  10. 34  src/content/WTR_base.js
  11. 27  src/content/contents.rdf
  12. 48  src/content/editors/DomUtils.js
  13. 114  src/content/editors/editor.js
  14. 43  src/content/editors/itest2.html
  15. 181  src/content/editors/itest2_editor.js
  16. 44  src/content/editors/watir.html
  17. 156  src/content/editors/watir_editor.js
  18. BIN  src/content/itest2.png
  19. 49  src/content/itest2recorder.css
  20. 72  src/content/itest2recorder.js
  21. 73  src/content/itest2recorder.xul
  22. 54  src/content/itest2recorderTest.js
  23. 49  src/content/itestrecorder.css
  24. 102  src/content/log.js
  25. 20  src/content/myThis.js
  26. 26  src/content/myThisTest.js
  27. 454  src/content/overlay.js
  28. 46  src/content/overlay.xul
  29. 39  src/content/overlayTest.js
  30. 37  src/content/preferences.js
  31. BIN  src/content/record.png
  32. BIN  src/content/recording.png
  33. 83  src/content/sidebar.js
  34. 34  src/content/stylesheet_utils.js
  35. BIN  src/content/test/forms/groovy.png
  36. 100  src/content/test/forms/index.html
  37. 23  src/content/test/frames/index.html
  38. 26  src/content/test/frames/leftFrame.html
  39. 29  src/content/test/index.html
  40. 28  src/content/test/links/index.html
  41. 41  src/content/tools.js
  42. 420  src/content/webtest-steps.js
  43. 60  src/content/webtest.css
  44. 14  src/defaults/preferences/wtr.js
  45. 32  src/install.rdf
  46. 3  src/locale/en-US/itest2recorder/overlay.dtd
  47. 25  src/update.rdf
  48. 24  src/update.rdf.tpl.xml
  49. 106  test.html
16  ChangeLog.txt
... ...
@@ -0,0 +1,16 @@
  1
+1.0.3
  2
+ Record file upload
  3
+ Display correct comment "#" instead of "//" 
  4
+
  5
+1.0.2
  6
+ [Fixes - TODO] not recording checkbox by id
  7
+ [Feature] Add the help text at the bottom of the editor
  8
+ [Fixes] iTest2 select by id does not record text
  9
+ [Enhancements] Test page 
  10
+
  11
+1.0.1 Recorder (2008-12-01)
  12
+==============
  13
+ [Feature] Add Watir recording
  14
+ [Feature] Support click link with id when there is not name field
  15
+ [Feature] Support textarea
  16
+ [Fixes] Checkbox now working correctly
23  License.txt
... ...
@@ -0,0 +1,23 @@
  1
+Copyright (c) 2008 AgileWay.
  2
+
  3
+All rights reserved. This program and the accompanying materials
  4
+are made available under the terms of the Eclipse Public License v1.0
  5
+which accompanies this distribution, and is available at
  6
+http://www.eclipse.org/legal/epl-v10.html
  7
+
  8
+Contributors:
  9
+  Zhimin Zhan
  10
+
  11
+The plugin is based on WebTestRecorder, http://webtestrecorder.canoo.com
  12
+its license as below.
  13
+---------------------
  14
+
  15
+Copyright (c) 2006 Marc Guillemot.
  16
+All rights reserved. This program and the accompanying materials
  17
+are made available under the terms of the Eclipse Public License v1.0
  18
+which accompanies this distribution, and is available at
  19
+http://www.eclipse.org/legal/epl-v10.html
  20
+
  21
+Contributors:
  22
+  Marc Guillemot - initial version
  23
+
BIN  ant-jars/js-1.6R7.jar
Binary file not shown
6  build.base.properties
... ...
@@ -0,0 +1,6 @@
  1
+updateLink=http://itest2.com/webtestrecorder.xpi
  2
+updateUrl=http://itest2.com/webtestrecorder-dist/update.rdf?reqVersion=%REQ_VERSION%&itemId=%ITEM_ID%&itemVersion=%ITEM_VERSION%&itemMayAppVersion=%ITEM_MAXAPPVERSION%&appId=%APP_ID%&appVersion=%APP_VERSION%&appOS%APP_OS%&appAbi%APP_ABI%
  3
+
  4
+extension.id={b632a045-55b8-4a21-8e6e-6e99f60f9c23}
  5
+# would only work for Firefox 1.5
  6
+#extension.id=WebtestRecorder@internetzky.de
185  build.xml
... ...
@@ -0,0 +1,185 @@
  1
+<?xml version="1.0" encoding="ISO-8859-1"?>
  2
+
  3
+<!--
  4
+/*******************************************************************************
  5
+ * Copyright (c) 2006 Marc Guillemot.
  6
+ * All rights reserved. This program and the accompanying materials
  7
+ * are made available under the terms of the Eclipse Public License v1.0
  8
+ * which accompanies this distribution, and is available at
  9
+ * http://www.eclipse.org/legal/epl-v10.html
  10
+ *
  11
+ * Contributors:
  12
+ *    Marc Guillemot - initial version
  13
+ *******************************************************************************/
  14
+-->
  15
+
  16
+<project name="itest2recorder" default="create-xpi">
  17
+
  18
+  <!-- load properties from custom and base property files (if they exist) -->
  19
+  <property file="build.properties"/>
  20
+  <property file="build.base.properties"/>
  21
+
  22
+  <property name="remote.repository" value="http://www.ibiblio.org/maven"/>
  23
+
  24
+
  25
+  <property name="jars.dir" value="ant-jars"/>
  26
+  <property name="targetDir" value="target"/>
  27
+  <property name="distDir" value="dist/dist"/>
  28
+  <property name="rhinoJar" value="${jars.dir}/js-1.6R7.jar"/>
  29
+
  30
+  <property name="update.path" value="http://itest2.com/releases"/>
  31
+  <property name="RELEASE" value=""/>
  32
+  <property name="VERSION" value="1.0"/>
  33
+
  34
+  <!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
  35
+  <target name="prepare" description="creates the directories">
  36
+    <tstamp>
  37
+      <format property="today" pattern="yyyyMMdd"/>
  38
+    </tstamp>
  39
+    <!-- <buildnumber/> -->
  40
+    <property name="versionNumber" value="0.9.${today}"/>
  41
+    <echo message="Extension version: ${versionNumber}"/>
  42
+    <mkdir dir="${targetDir}"/>
  43
+    <mkdir dir="${targetDir}/chrome"/>
  44
+    <mkdir dir="${targetDir}/src"/>
  45
+    <mkdir dir="${targetDir}/dist"/>
  46
+  </target>
  47
+
  48
+  <target name="clean">
  49
+    <delete dir="${targetDir}"/>
  50
+  </target>
  51
+
  52
+  <!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
  53
+  <target name="create-jar" depends="compile, test">
  54
+    <zip destfile="${targetDir}/chrome/${ant.project.name}.jar">
  55
+      <fileset dir="${targetDir}/src">
  56
+        <include name="content/**"/>
  57
+        <include name="locale/**/*"/>
  58
+        <include name="defaults/**/*"/>
  59
+      </fileset>
  60
+    </zip>
  61
+  </target>
  62
+
  63
+  <!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
  64
+  <target name="test" depends="compile" description="runs the unit tests">
  65
+    <java dir="target/classes/content" classname="org.mozilla.javascript.tools.shell.Main" failonerror="true"
  66
+          logError="true"
  67
+          classpath="${rhinoJar}" fork="true">
  68
+      <arg line="-f itest2recorderTest.js overlayTest.js myThisTest.js"/>
  69
+    </java>
  70
+  </target>
  71
+
  72
+  <!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
  73
+  <target name="compile" depends="prepare, get-dependencies" description="pseudo compilation">
  74
+    <mkdir dir="${targetDir}/classes"/>
  75
+    <!-- remove "const " as rhino seem to dislike it -->
  76
+    <copy todir="${targetDir}/classes" overwrite="true">
  77
+      <fileset dir="src" includes="**/*.js"/>
  78
+      <filterset begintoken="c" endtoken=" ">
  79
+        <filter token="onst" value=""/>
  80
+      </filterset>
  81
+    </copy>
  82
+    <echo message="running js compiler on script files"/>
  83
+    <apply executable="java" failonerror="true" logError="true">
  84
+      <arg value="-cp"/>
  85
+      <arg value="${rhinoJar}"/>
  86
+      <arg value="org.mozilla.javascript.tools.jsc.Main"/>
  87
+
  88
+      <fileset dir="${targetDir}/classes" includes="**/*.js"/>
  89
+    </apply>
  90
+
  91
+    <mkdir dir="${targetDir}/src"/>
  92
+    <copy todir="${targetDir}/src" overwrite="true">
  93
+      <fileset dir="src">
  94
+        <include name="install.rdf"/>
  95
+        <include name="chrome.manifest"/>
  96
+        <include name="update.rdf"/>
  97
+      </fileset>
  98
+      <filterset>
  99
+        <filter token="versionNumber" value="${versionNumber}"/>
  100
+        <filter token="updateLink" value="${updateLink}"/>
  101
+        <filter token="updateUrl" value="${updateUrl}"/>
  102
+        <filter token="extension.id" value="${extension.id}"/>
  103
+      </filterset>
  104
+    </copy>
  105
+
  106
+    <copy todir="${targetDir}/dist" overwrite="true">
  107
+      <fileset dir="${targetDir}/src">
  108
+        <include name="update.rdf"/>
  109
+      </fileset>
  110
+    </copy>
  111
+
  112
+    <property name="binaries" value="**/*.png"/>
  113
+    <copy todir="${targetDir}/src" overwrite="true">
  114
+      <fileset dir="src" excludes="${binaries}">
  115
+        <include name="content/**/*"/>
  116
+        <include name="locale/**/*"/>
  117
+        <include name="defaults/**/*"/>
  118
+      </fileset>
  119
+      <filterset>
  120
+        <filter token="Copyright Marc Guillemot" value="Copyright 2005 - 2006 © Marc Guillemot"/>
  121
+        <filter token="versionNumber" value="${versionNumber}"/>
  122
+      </filterset>
  123
+    </copy>
  124
+    <copy todir="${targetDir}/src" overwrite="true">
  125
+      <fileset dir="src" includes="${binaries}"/>
  126
+    </copy>
  127
+  </target>
  128
+
  129
+  <!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
  130
+  <target name="create-xpi" depends="create-jar, expand-update-template">
  131
+    <echo message="Creating XPI file"/>
  132
+    <zip destfile="${targetDir}/dist/${ant.project.name}.xpi">
  133
+      <fileset dir="${targetDir}">
  134
+        <include name="chrome/*"/>
  135
+      </fileset>
  136
+      <fileset dir="${targetDir}/src">
  137
+        <include name="install.rdf"/>
  138
+        <include name="chrome.manifest"/>
  139
+        <include name="defaults/**"/>
  140
+        <include name="locale/**"/>
  141
+      </fileset>
  142
+    </zip>
  143
+  </target>
  144
+
  145
+  <!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
  146
+  <target name="dist" depends="create-xpi" description="copies the generated files where they can be downloaded">
  147
+    <echo message="Copying to ${distDir}"/>
  148
+    <copy todir="${distDir}" overwrite="true">
  149
+      <fileset dir="${targetDir}/dist" includes="*"/>
  150
+    </copy>
  151
+  </target>
  152
+
  153
+  <!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
  154
+  <target name="get-dependencies" unless="skip.get-dependencies"
  155
+          description="Get all the required dependencies from a remote repository">
  156
+    <mkdir dir="${jars.dir}"/>
  157
+
  158
+    <!--<get usetimestamp="true"-->
  159
+    <!--src="${remote.repository}/rhino/jars/js-1.6R7.jar"-->
  160
+    <!--dest="${jars.dir}/js-1.6R7.jar"/>-->
  161
+  </target>
  162
+
  163
+  <!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
  164
+  <target name="cruise" depends="dist"
  165
+          description="to be started by the CruiseControl build server">
  166
+  </target>
  167
+
  168
+
  169
+  <target name="expand-update-template"  unless="update.expansion.notRequired">
  170
+    <copy file="src/update.rdf.tpl.xml"
  171
+          tofile="${targetDir}/dist/update.rdf"
  172
+          overwrite="true">
  173
+      <filterchain>
  174
+        <replacetokens>
  175
+          <token key="VERSION" value="${VERSION}"/>
  176
+          <token key="RELEASE" value="${RELEASE}"/>
  177
+          <token key="LEAF" value="itest2recorder-${VERSION}${RELEASE}.xpi"/>
  178
+          <token key="UPDATEPATH" value="${update.path}/firebug/${VERSION}"/>
  179
+        </replacetokens>
  180
+      </filterchain>
  181
+    </copy>
  182
+    <echo message="expanded src/update.rdf.tpl.xml"/>
  183
+  </target>
  184
+
  185
+</project>
3  src/chrome.manifest
... ...
@@ -0,0 +1,3 @@
  1
+content	itest2recorder	jar:chrome/itest2recorder.jar!/content/
  2
+locale  itest2recorder en-US       jar:chrome/itest2recorder.jar!/locale/en-US/itest2recorder/
  3
+overlay	chrome://browser/content/browser.xul	chrome://itest2recorder/content/overlay.xul
64  src/content/UnitTestUtils.js
... ...
@@ -0,0 +1,64 @@
  1
+
  2
+var window = { addEventListener: function() {} };
  3
+
  4
+/**
  5
+Unit tests utilities
  6
+*/
  7
+
  8
+function assertEquals(_oExpected, _oReal)
  9
+{
  10
+	if (_oExpected != _oReal)
  11
+	{
  12
+		var strExpected = String(_oExpected);
  13
+		var strReal = String(_oReal);
  14
+		var iFirstDiff = 0;
  15
+		for (iFirstDiff=0; iFirstDiff<strExpected.length; ++iFirstDiff)
  16
+		{
  17
+			if (strExpected.charAt(iFirstDiff) != strReal.charAt(iFirstDiff))
  18
+				break;
  19
+		}
  20
+		throw "assertEquals failed: expected: \n>" + _oExpected + "<\n, but got: \n>" + _oReal
  21
+			+ "<\nFirst diff at position " + iFirstDiff
  22
+			+ ": " + strExpected.charAt(iFirstDiff) + " <> " + strReal.charAt(iFirstDiff);
  23
+	}
  24
+	print("Assertion passed");
  25
+}
  26
+
  27
+function assertUndefined(_oReal)
  28
+{
  29
+	if (undefined != _oReal)
  30
+	{
  31
+		throw "assertUndefined failed: found: " + _oReal;
  32
+	}
  33
+	print("Assertion passed");
  34
+}
  35
+
  36
+function runTest(_testFunction)
  37
+{
  38
+	try
  39
+	{
  40
+		_testFunction();
  41
+	}
  42
+	catch (e)
  43
+	{
  44
+		print(e.message + " [" + e.lineNumber + "]");
  45
+		print(e.caller);
  46
+		for (var i in e)
  47
+		{
  48
+			print(i + ": " + e[i]);
  49
+		}
  50
+		throw e;
  51
+	}
  52
+}
  53
+
  54
+function runTests()
  55
+{
  56
+	for (var i in this)
  57
+	{
  58
+		if (typeof this[i] == "function" && i.indexOf("test") == 0)
  59
+		{
  60
+			print(i);
  61
+			runTest(this[i])
  62
+		}
  63
+	}
  64
+}
62  src/content/WTREditorCtxMenu.js
... ...
@@ -0,0 +1,62 @@
  1
+var WTREditorCtxMenu = {}
  2
+
  3
+/**
  4
+Delete all the recorded node in the displayed editor
  5
+*/
  6
+WTREditorCtxMenu.deleteAll = function(_oMenuItem)
  7
+{
  8
+	var element = document.popupNode;
  9
+	var body = element.ownerDocument.body
  10
+	while (body.lastChild)
  11
+	{
  12
+		body.removeChild(body.lastChild)
  13
+	}
  14
+}
  15
+
  16
+/**
  17
+Copies all steps to the clipboard
  18
+*/
  19
+WTREditorCtxMenu.copyToClipboard = function()
  20
+{
  21
+	const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
  22
+		.getService(Components.interfaces.nsIClipboardHelper);
  23
+	var element = document.popupNode;
  24
+	var editorWindow = element.ownerDocument.defaultView
  25
+	gClipboardHelper.copyString(editorWindow.getAsText());
  26
+}
  27
+
  28
+
  29
+
  30
+WTREditorCtxMenu.onPopupShowing = function(_oMenu)
  31
+{
  32
+	var element = document.popupNode;
  33
+	var fnGetAlternatives = element.ownerDocument.defaultView.getAlternative
  34
+	var nbAlternativeFound = 0;
  35
+	var bHideNoAlternativeFound = true;
  36
+	if (fnGetAlternatives)
  37
+	{
  38
+		var alternatives = fnGetAlternatives(element)
  39
+		nbAlternativeFound = alternatives.length
  40
+		for (var i=0; i<nbAlternativeFound; ++i)
  41
+		{
  42
+			var oMenuItem = document.getElementById('alternative' + i)
  43
+			oMenuItem.label = "Replace with: " + alternatives[i].label
  44
+			oMenuItem.wtrStepNode = alternatives[i].node
  45
+			oMenuItem.hidden = false
  46
+		}
  47
+		bHideNoAlternativeFound = (nbAlternativeFound != 0);
  48
+	}
  49
+
  50
+	for (var i=nbAlternativeFound; i<5; ++i)
  51
+	{
  52
+		var oMenuItem = document.getElementById('alternative' + i)
  53
+		oMenuItem.hidden = true
  54
+	}
  55
+	document.getElementById('editorCtxMenu_noAlternative').hidden = bHideNoAlternativeFound
  56
+}
  57
+
  58
+WTREditorCtxMenu.showAlternative = function(_oMenuItem)
  59
+{
  60
+	var oStepNode = _oMenuItem.wtrStepNode
  61
+	oStepNode.ownerDocument.defaultView.activeAlternative(oStepNode)
  62
+}
57  src/content/WTRStep.js
... ...
@@ -0,0 +1,57 @@
  1
+
  2
+/**
  3
+ webtest specials
  4
+Contains object definition
  5
+*/
  6
+
  7
+function WTRStep(_stepName, _attributes)
  8
+{
  9
+	this.wtrStep = _stepName;
  10
+	for (var i in _attributes)
  11
+	{
  12
+		this[i] = _attributes[i];
  13
+	}
  14
+	this.getPropertyNames = function()
  15
+	{
  16
+		var tabPropNames = new Array();
  17
+		for (var strPropName in this)
  18
+		{
  19
+      if (strPropName.indexOf("wtr") != 0
  20
+				&& (typeof this[strPropName] == "string"))
  21
+			{
  22
+				tabPropNames.push(strPropName);
  23
+			}
  24
+		}
  25
+		return tabPropNames
  26
+	}
  27
+
  28
+	this.getSortedPropertyNames = function()
  29
+	{
  30
+		var tabPropNames = this.getPropertyNames()
  31
+		tabPropNames.sort();
  32
+		return tabPropNames;
  33
+	}
  34
+
  35
+	this.clone = function()
  36
+	{
  37
+		var name = this.wtrStep
  38
+		var props = {}
  39
+		var tabPropNames = this.getPropertyNames()
  40
+		for (var i=0; i<tabPropNames.length; ++i)
  41
+		{
  42
+			var propName = tabPropNames[i]
  43
+			props[propName] = this[propName]
  44
+		}
  45
+		return new WTRStep(name, props)
  46
+	}
  47
+
  48
+	this.cloneAndAdd = function(properties)
  49
+	{
  50
+		var clone = this.clone()
  51
+		for (var i in properties)
  52
+		{
  53
+			clone[i] = properties[i]
  54
+		}
  55
+		return clone;
  56
+	}
  57
+}
34  src/content/WTR_base.js
... ...
@@ -0,0 +1,34 @@
  1
+
  2
+function WTR_base()
  3
+{
  4
+}
  5
+
  6
+/**
  7
+Gets the webtest recorder associated to the current window
  8
+*/
  9
+WTR_base.prototype._getWebtestRecorder = function()
  10
+{
  11
+	var oWTRWin = this._getRecorderWindow();
  12
+	if (oWTRWin == null)
  13
+		return null;
  14
+
  15
+	return oWTRWin.wtr_WebtestRecorder;
  16
+}
  17
+
  18
+WTR_base.prototype._getRecorderWindow = function()
  19
+{
  20
+	if (parent)
  21
+		return parent.wtrWindow;
  22
+	return null;
  23
+}
  24
+
  25
+
  26
+/**
  27
+Gets the window in the current browser
  28
+*/
  29
+WTR_base.prototype._getCurrentWindow = function()
  30
+{
  31
+	var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
  32
+	var window = wm.getMostRecentWindow("navigator:browser");
  33
+	return window.getBrowser().contentWindow;
  34
+}
27  src/content/contents.rdf
... ...
@@ -0,0 +1,27 @@
  1
+<?xml version="1.0"?>
  2
+
  3
+<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  4
+         xmlns:chrome="http://www.mozilla.org/rdf/chrome#"> 
  5
+		   
  6
+  <RDF:Seq about="urn:mozilla:package:root">
  7
+    <RDF:li resource="urn:mozilla:package:itest2recorder"/>
  8
+  </RDF:Seq>
  9
+  
  10
+  <RDF:Description about="urn:mozilla:package:itest2recorder"
  11
+    chrome:displayName="iTest Recorder"
  12
+    chrome:author="Zhimin Zhan"
  13
+    chrome:authorURL="http://itest2.com"
  14
+    chrome:name="itest2recorder"
  15
+    chrome:extension="true"
  16
+    chrome:description="Captures your actions in Firefox and generates RWebUnit tests/specs">
  17
+  </RDF:Description>
  18
+ 
  19
+  <RDF:Seq about="urn:mozilla:overlays">
  20
+    <RDF:li resource="chrome://browser/content/browser.xul"/>
  21
+  </RDF:Seq>
  22
+    
  23
+  <RDF:Seq about="chrome://browser/content/browser.xul">
  24
+    <RDF:li>chrome://itest2recorder/content/overlay.xul</RDF:li>
  25
+  </RDF:Seq>
  26
+
  27
+</RDF:RDF>
48  src/content/editors/DomUtils.js
... ...
@@ -0,0 +1,48 @@
  1
+/*******************************************************************************
  2
+ * Copyright (c) 2006 Marc Guillemot.
  3
+ * All rights reserved. This program and the accompanying materials
  4
+ * are made available under the terms of the Eclipse Public License v1.0
  5
+ * which accompanies this distribution, and is available at
  6
+ * http://www.eclipse.org/legal/epl-v10.html
  7
+ *
  8
+ * Contributors:
  9
+ *    Marc Guillemot - initial version
  10
+ *******************************************************************************/
  11
+
  12
+/**
  13
+Contains utilities for DOM node manipulation
  14
+*/
  15
+
  16
+const WTR_DomUtils = {};
  17
+
  18
+
  19
+/**
  20
+Creates a text node and appends it to the children of the provided node
  21
+@param _oNode the DOM node to which a text node should be appended
  22
+@param _strText the text for the text node
  23
+*/
  24
+WTR_DomUtils.appendTextToNode = function(_oNode, _strText)
  25
+{
  26
+	_oNode.appendChild(_oNode.ownerDocument.createTextNode(_strText));
  27
+}
  28
+
  29
+/**
  30
+Creates a new element node and appends it to the children of the provided node
  31
+@param _oNode the node to which a not should be appended
  32
+@param _strNodeName the name of the node to create
  33
+@param _mapAttributes (optional) the attributes to set on the node to create
  34
+@param _strText (optional) the text content for the node to create
  35
+@return the newly created node
  36
+*/
  37
+WTR_DomUtils.appendNodeToNode = function(_oNode, _strNodeName, _mapAttributes, _strText)
  38
+{
  39
+	var oNode = _oNode.ownerDocument.createElement(_strNodeName);
  40
+	for (var i in _mapAttributes)
  41
+	{
  42
+		oNode.setAttribute(i, _mapAttributes[i]);
  43
+	}
  44
+	if (_strText)
  45
+		this.appendTextToNode(oNode, _strText);
  46
+	_oNode.appendChild(oNode);
  47
+	return oNode;
  48
+}
114  src/content/editors/editor.js
... ...
@@ -0,0 +1,114 @@
  1
+/*******************************************************************************
  2
+ * Copyright (c) 2007 Marc Guillemot.
  3
+ * All rights reserved. This program and the accompanying materials
  4
+ * are made available under the terms of the Eclipse Public License v1.0
  5
+ * which accompanies this distribution, and is available at
  6
+ * http://www.eclipse.org/legal/epl-v10.html
  7
+ *
  8
+ * Contributors:
  9
+ *    Marc Guillemot - initial version
  10
+ *******************************************************************************/
  11
+function init()
  12
+{
  13
+	document.designMode = "on"
  14
+	document.body.removeChild(document.body.firstChild)
  15
+}
  16
+
  17
+window.addEventListener("load", init, false);
  18
+var createDOMNode_XXXRepresentation; // needs to be set by extension
  19
+var nbNodes = 0;
  20
+
  21
+function addWebTestStep(_possibleSteps)
  22
+{
  23
+	var oStepVariationsContainer = document.createElement("div");
  24
+	oStepVariationsContainer.setAttribute("wt-type", "container")
  25
+	if (_possibleSteps.push) // an array
  26
+	{
  27
+		for (var i=0; i<_possibleSteps.length; ++i)
  28
+		{
  29
+			addSingleStep(oStepVariationsContainer, _possibleSteps[i], i==0)
  30
+		}
  31
+	}
  32
+	else
  33
+		addSingleStep(oStepVariationsContainer, _possibleSteps, true)
  34
+
  35
+	document.body.appendChild(oStepVariationsContainer);
  36
+}
  37
+
  38
+function setCreateDOMNode_XXXRepresentation(_fn)
  39
+{
  40
+	createDOMNode_XXXRepresentation = _fn
  41
+	parent.wtr_WebtestRecorder.registerListener(addWebTestStep);
  42
+}
  43
+
  44
+/**
  45
+Gets the content of the window as formated text
  46
+*/
  47
+function getAsText()
  48
+{
  49
+	var str = ""
  50
+	for (var i=0; i<document.body.childNodes.length; ++i)
  51
+	{
  52
+		var o = document.body.childNodes[i];
  53
+		if (o.visibleStepNode)
  54
+			str += o.visibleStepNode.textContent + "\n"
  55
+	}
  56
+	return str
  57
+}
  58
+
  59
+function getAlternative(_oNode)
  60
+{
  61
+	var oContainer = getContainer(_oNode)
  62
+	if (oContainer == null)
  63
+		return []
  64
+
  65
+	var alternatives = []
  66
+	for (var i=0; i<oContainer.childNodes.length; ++i)
  67
+	{
  68
+		var oChild = oContainer.childNodes[i]
  69
+		if (oContainer.visibleStepNode != oChild)
  70
+			alternatives.push({label: oChild.textContent, node: oChild})
  71
+	}
  72
+	return alternatives
  73
+}
  74
+
  75
+/**
  76
+@param _oStepNode the step node that should become visible
  77
+*/
  78
+function activeAlternative(_oStepNode)
  79
+{
  80
+	var oContainer = getContainer(_oStepNode)
  81
+	oContainer.visibleStepNode.setAttribute("class", "alternativeStep")
  82
+	oContainer.visibleStepNode = _oStepNode
  83
+	_oStepNode.removeAttribute("class")
  84
+}
  85
+
  86
+function addSingleStep(_oContainer, _oStep, bVisible)
  87
+{
  88
+	var oNode = createDOMNode_XXXRepresentation(_oStep, document, bVisible);
  89
+	oNode.setAttribute("wt-type", "step")
  90
+	oNode.id = "step" + (++nbNodes)
  91
+	_oContainer.appendChild(oNode);
  92
+	if (bVisible)
  93
+		_oContainer.visibleStepNode = oNode
  94
+}
  95
+
  96
+function getContainer(_oNode)
  97
+{
  98
+	return getParentNodeWithType(_oNode, "container")
  99
+}
  100
+
  101
+function getTargetedStep(_oNode)
  102
+{
  103
+	return getParentNodeWithType(_oNode, "step")
  104
+}
  105
+
  106
+function getParentNodeWithType(_oNode, _strType)
  107
+{
  108
+	if (!_oNode || !_oNode.getAttribute)
  109
+		return null
  110
+	else if (_oNode.getAttribute("wt-type") == _strType)
  111
+		return _oNode
  112
+	else
  113
+		return getParentNodeWithType(_oNode.parentNode, _strType)
  114
+}
43  src/content/editors/itest2.html
... ...
@@ -0,0 +1,43 @@
  1
+
  2
+<html>
  3
+<head>
  4
+<title>iTest XML Editor</title>
  5
+<script type="text/javascript" src="DomUtils.js"></script>
  6
+<script type="text/javascript" src="editor.js"></script>
  7
+<script type="text/javascript" src="itest2_editor.js"></script>
  8
+<style>
  9
+body
  10
+{
  11
+	font-family: Courier, "Courier New", monospace;
  12
+	font-size: smaller;
  13
+	background-color: #FFFFFF;
  14
+}
  15
+.junit
  16
+{
  17
+	color: #ff5555;
  18
+}
  19
+.text
  20
+{
  21
+	color: #A020F0;
  22
+}
  23
+div
  24
+{
  25
+	text-indent: -5px
  26
+}
  27
+div > div
  28
+{
  29
+	margin-left: 10px;
  30
+}
  31
+.alternativeStep
  32
+{
  33
+	display: none;
  34
+}
  35
+.comment
  36
+{
  37
+	color: #00ff00;
  38
+}
  39
+</style>
  40
+</head>
  41
+<body>
  42
+</body>
  43
+</html>
181  src/content/editors/itest2_editor.js
... ...
@@ -0,0 +1,181 @@
  1
+/*******************************************************************************
  2
+ * Copyright (c) 2007-2008 Marc Guillemot.
  3
+ * All rights reserved. This program and the accompanying materials
  4
+ * are made available under the terms of the Eclipse Public License v1.0
  5
+ * which accompanies this distribution, and is available at
  6
+ * http://www.eclipse.org/legal/epl-v10.html
  7
+ *
  8
+ * Contributors:
  9
+ *    Marc Guillemot - initial version
  10
+ *******************************************************************************/
  11
+
  12
+/**
  13
+ Creates a DOM node to represent the step as WebDriver code
  14
+ @param _document the document to which the node will be added
  15
+ @param _oStep the step to represent
  16
+ @return the DOM node to insert in the document
  17
+ */
  18
+function createDOMNode_iTest2Representation(_oStep, _document, bVisible)
  19
+{
  20
+  var oStepNode = _document.createElement("div");
  21
+  if (!bVisible)
  22
+  {
  23
+    oStepNode.setAttribute("class", "alternativeStep")
  24
+  }
  25
+
  26
+  var conversion = conversions[_oStep.wtrStep]
  27
+  if (conversion)
  28
+  {
  29
+    var txt = conversion(_oStep);
  30
+    if (txt.indexOf("assertEquals") == 0)
  31
+    {
  32
+      txt = txt.substr("assertEquals".length)
  33
+      WTR_DomUtils.appendNodeToNode(oStepNode, "span", {"class": "junit"}, "assertEquals");
  34
+    }
  35
+    var oNode = WTR_DomUtils.appendNodeToNode(oStepNode, "span", {}, "");
  36
+    txt = txt.replace(/"([^\"]*)"/g, '"<span class="text">$1</span>"')
  37
+    oNode.innerHTML = txt
  38
+  }
  39
+  else
  40
+    WTR_DomUtils.appendNodeToNode(oStepNode, "span", {"class": "comment"}, "# can't yet handle " + _oStep.wtrStep);
  41
+
  42
+  return oStepNode;
  43
+}
  44
+
  45
+// this registers the editor as listener too
  46
+setCreateDOMNode_XXXRepresentation(createDOMNode_iTest2Representation)
  47
+
  48
+var conversions = {}
  49
+conversions["invoke"] = function(oStep)
  50
+{
  51
+  return 'goto_page("' + oStep.url + '")'
  52
+}
  53
+
  54
+conversions["verifyTitle"] = function(oStep)
  55
+{
  56
+  return 'assert_title("' + oStep.text + '")'
  57
+}
  58
+
  59
+conversions["verifyText"] = function(oStep)
  60
+{
  61
+  return 'assert_text_present("' + oStep.text + '")'
  62
+}
  63
+
  64
+conversions["clickLink"] = function(oStep)
  65
+{
  66
+  var by = ""
  67
+  if (oStep.htmlId)
  68
+    by = 'click_link_with_id("' + oStep.htmlId + '")'
  69
+  else if (oStep.label)
  70
+    by = 'click_link("' + oStep.label + '")'
  71
+
  72
+  return by;
  73
+}
  74
+
  75
+conversions["clickButton"] = function(oStep)
  76
+{
  77
+  var by = ""
  78
+  if (oStep.htmlId)
  79
+    by = 'click_button_with_id("' + oStep.htmlId + '")'
  80
+  else if (oStep.label)
  81
+    by = 'click_button("' + oStep.label + '")'
  82
+
  83
+  return by;
  84
+}
  85
+
  86
+function identifyInputField(oStep)
  87
+{
  88
+  var by = ""
  89
+  if (oStep.htmlId)
  90
+    by = '(:id, "' + oStep.htmlId + '")'
  91
+  else if (oStep.forLabel)
  92
+    by = '(:text, "' + oStep.forLabel + '")'
  93
+  else if (oStep.name)
  94
+    by = '(:name, "' + oStep.name + '")'
  95
+  else if (oStep.value)
  96
+    by = '(:value, "' + oStep.value + '")'
  97
+  else if (oStep.xpath)
  98
+    by = 'xpath("' + oStep.xpath + '")'
  99
+  return by
  100
+}
  101
+
  102
+
  103
+conversions["setFileField"] = function(oStep)
  104
+{
  105
+  oStep.value = oStep.fileName
  106
+  if (oStep.name) {
  107
+    return 'select_file_for_upload("' + oStep.name + '", "' + oStep.fileName + '")'    
  108
+  } else {
  109
+    return conversions["setInputField"](oStep)
  110
+  }
  111
+}
  112
+
  113
+conversions["setRadioButton"] = function(oStep)
  114
+{
  115
+  return 'click_radio_option("' + oStep.name + '", "' + oStep.value + '")'
  116
+}
  117
+
  118
+conversions["setCheckbox"] = function(oStep)
  119
+{
  120
+  var checkbox_cmd = (oStep.checked == "true") ? "check_checkbox" : "uncheck_checkbox";
  121
+  if (oStep.name) {
  122
+    if (oStep.value) {
  123
+      return checkbox_cmd + '("' + oStep.name + '", "' + oStep.value + '")';
  124
+    } else {
  125
+      return checkbox_cmd + '("' + oStep.name + '")';
  126
+    }
  127
+  } else if (oStep.htmlId) {
  128
+    return (oStep.checked == "true") ? 'checkbox(:id,"' + oStep.htmlId +  '").set' : 'checkbox(:id,"' + oStep.htmlId +  '").clear'
  129
+  } else {
  130
+    return "checkbox operation not supported"
  131
+  }
  132
+}
  133
+
  134
+conversions["setSelectField"] = function(oStep)
  135
+{
  136
+  if (oStep.name) {
  137
+    return 'select_option("' + oStep.name + '", "' + oStep.text + '")'
  138
+  } else if (oStep.htmlId) {
  139
+    return 'select_list' + '(:id, "' + oStep.htmlId + '").set("' + oStep.text + '")'
  140
+  } else {
  141
+    return 'select_option("specify_name_here", "' + oStep.text + '")'
  142
+  }
  143
+
  144
+}
  145
+
  146
+conversions["setInputField"] = function(oStep)
  147
+{
  148
+  var tagName = "text_field";
  149
+  if (oStep.tagName == "TEXTAREA") {
  150
+    tagName = "area";
  151
+  }
  152
+
  153
+  if (oStep.name) {
  154
+    return 'enter_text("' + oStep.name + '", "' + oStep.value + '")'
  155
+  } else if (oStep.htmlId) {
  156
+    // TODO, what happen textArea
  157
+    return tagName + '(:id, "' + oStep.htmlId + '").set("' + oStep.value + '")'
  158
+  } else {
  159
+    return tagName + '(:id, "specify_id_here").set("' + oStep.value + '")'
  160
+  }
  161
+}
  162
+
  163
+conversions["verifyInputField"] = function(oStep)
  164
+{
  165
+  var tagName = "text_field";
  166
+  if (oStep.tagName == "TEXTAREA") {
  167
+    tagName = "area";
  168
+  }
  169
+
  170
+  if (oStep.htmlId) {
  171
+    return tagName + '(:id, "' + oStep.htmlId + '").value.should == "' + oStep.value + '"'
  172
+  } else if (oStep.name) {
  173
+    return tagName + '(:name, "' + oStep.name + '").value.should == "' + oStep.value + '"'
  174
+  } else {
  175
+    return tagName + '(:id, "specify_id_here").value.should == "' + oStep.value + '"'
  176
+  }
  177
+}
  178
+
  179
+
  180
+
  181
+
44  src/content/editors/watir.html
... ...
@@ -0,0 +1,44 @@
  1
+
  2
+<html>
  3
+<head>
  4
+<title>Watir Editor</title>
  5
+<script type="text/javascript" src="DomUtils.js"></script>
  6
+<script type="text/javascript" src="editor.js"></script>
  7
+<script type="text/javascript" src="watir_editor.js"></script>
  8
+<style>
  9
+body
  10
+{
  11
+	font-family: Courier, "Courier New", monospace;
  12
+	font-size: smaller;
  13
+	background-color: #FFFFFF;
  14
+}
  15
+.junit
  16
+{
  17
+	color: #ff5555;
  18
+}
  19
+.text
  20
+{
  21
+	color: #A020F0;
  22
+}
  23
+div
  24
+{
  25
+	text-indent: -5px
  26
+}
  27
+div > div
  28
+{
  29
+	margin-left: 10px;
  30
+}
  31
+.alternativeStep
  32
+{
  33
+	display: none;
  34
+}
  35
+.comment
  36
+{
  37
+	color: #00ff00;
  38
+}
  39
+</style>
  40
+</head>
  41
+<body>
  42
+
  43
+</body>
  44
+</html>
156  src/content/editors/watir_editor.js
... ...
@@ -0,0 +1,156 @@
  1
+/**
  2
+ Creates a DOM node to represent the step as WebDriver code
  3
+ @param _document the document to which the node will be added
  4
+ @param _oStep the step to represent
  5
+ @return the DOM node to insert in the document
  6
+ */
  7
+function createDOMNode_WatirRepresentation(_oStep, _document, bVisible)
  8
+{
  9
+  var oStepNode = _document.createElement("div");
  10
+  if (!bVisible)
  11
+  {
  12
+    oStepNode.setAttribute("class", "alternativeStep")
  13
+  }
  14
+
  15
+  var conversion = conversions[_oStep.wtrStep]
  16
+  if (conversion)
  17
+  {
  18
+    var txt = conversion(_oStep);
  19
+    if (txt.indexOf("assertEquals") == 0)
  20
+    {
  21
+      txt = txt.substr("assertEquals".length)
  22
+      WTR_DomUtils.appendNodeToNode(oStepNode, "span", {"class": "junit"}, "assertEquals");
  23
+    }
  24
+    var oNode = WTR_DomUtils.appendNodeToNode(oStepNode, "span", {}, "");
  25
+    txt = txt.replace(/"([^\"]*)"/g, '"<span class="text">$1</span>"')
  26
+    oNode.innerHTML = txt
  27
+  }
  28
+  else
  29
+    WTR_DomUtils.appendNodeToNode(oStepNode, "span", {"class": "comment"}, "# can't yet handle " + _oStep.wtrStep);
  30
+
  31
+  return oStepNode;
  32
+}
  33
+
  34
+// this registers the editor as listener too
  35
+setCreateDOMNode_XXXRepresentation(createDOMNode_WatirRepresentation)
  36
+
  37
+var conversions = {}
  38
+conversions["invoke"] = function(oStep)
  39
+{
  40
+  return 'browser = Watir::Browser.start  "' + oStep.url + '"' 
  41
+}
  42
+
  43
+conversions["verifyTitle"] = function(oStep)
  44
+{
  45
+  // TODO if firefox, browser.title
  46
+  return 'browser.document.title.should == "' + oStep.text + '"'
  47
+}
  48
+
  49
+conversions["verifyText"] = function(oStep)
  50
+{
  51
+  return 'browser.text.include?("' + oStep.text + '").should == true'
  52
+}
  53
+
  54
+conversions["clickLink"] = function(oStep)
  55
+{
  56
+  var by = ""
  57
+  if (oStep.htmlId)
  58
+    by = 'browser.link(:id, "' + oStep.htmlId + '").click'
  59
+  else if (oStep.name)
  60
+    by = 'brower.link(:name, "' + oStep.name + '").click'
  61
+  else if (oStep.label)
  62
+    by = 'browser.link(:text, "' + oStep.label + '").click'
  63
+  return by;
  64
+}
  65
+
  66
+conversions["clickButton"] = function(oStep)
  67
+{
  68
+  //TODO: image button => ie.button(:src, /doit/).click
  69
+  var by = ""
  70
+  if (oStep.htmlId)
  71
+    by = 'browser.button(:id, "' + oStep.htmlId + '").click'
  72
+  else if (oStep.name)
  73
+    by = 'browser.button(:name, "' + oStep.name + '").click'
  74
+  else if (oStep.label)
  75
+    by = 'browser.button(:value,"' + oStep.label + '").click'
  76
+  return by;
  77
+}
  78
+
  79
+function identifyInputField(oStep)
  80
+{
  81
+  var by = ""
  82
+  if (oStep.htmlId)
  83
+    by = '(:id, "' + oStep.htmlId + '")'
  84
+  else if (oStep.forLabel)
  85
+    by = '(:text, "' + oStep.forLabel + '")'
  86
+  else if (oStep.name)
  87
+    by = '(:name, "' + oStep.name + '")'
  88
+  else if (oStep.value)
  89
+    by = '(:value, "' + oStep.value + '")'
  90
+  else if (oStep.xpath)
  91
+    by = 'xpath("' + oStep.xpath + '")'
  92
+  return by
  93
+}
  94
+
  95
+conversions["setInputField"] = function(oStep)
  96
+{
  97
+  var tagName = "text_field";
  98
+  if (oStep.tagName == "TEXTAREA") {
  99
+    tagName = "area";
  100
+  }
  101
+
  102
+  return 'browser.' + tagName + identifyInputField(oStep) + '.set("' + oStep.value + '")'
  103
+}
  104
+
  105
+conversions["setFileField"] = function(oStep)
  106
+{
  107
+  oStep.value = oStep.fileName
  108
+  if (oStep.name) {
  109
+    return 'browser.file_field(:name, "' + oStep.fileName + '").set("' + oStep.fileName + '")'
  110
+  } else if (oStep.htmlId) {
  111
+    return 'browser.file_field(:id, "' +  oStep.htmlId + '").set("' + oStep.fileName + '")'
  112
+  } else {
  113
+    return conversions["setInputField"](oStep)
  114
+  }
  115
+}
  116
+
  117
+conversions["setRadioButton"] = function(oStep)
  118
+{
  119
+  if (oStep.htmlId)
  120
+    by = 'browser.radio(:id, "' + oStep.htmlId + '").set'
  121
+  else if (oStep.name)
  122
+    by = 'browser.radio(:name, "' + oStep.name + '", "' + oStep.value + '").click'
  123
+  return by
  124
+}
  125
+
  126
+conversions["setCheckbox"] = function(oStep)
  127
+{
  128
+  if (oStep.checked == "true") {
  129
+    return 'browser.checkbox' + identifyInputField(oStep) + '.set'
  130
+  } else {
  131
+    return 'browser.checkbox' + identifyInputField(oStep) + '.clear'
  132
+  }
  133
+}
  134
+
  135
+conversions["setSelectField"] = function(oStep)
  136
+{
  137
+  return 'browser.select_list' + identifyInputField(oStep) + '.set("' + oStep.text + '")'
  138
+}
  139
+
  140
+
  141
+conversions["verifyInputField"] = function(oStep)
  142
+{
  143
+  var tagName = "browser.text_field";
  144
+  if (oStep.tagName == "TEXTAREA") {
  145
+    tagName = "browser.area";
  146
+  }
  147
+
  148
+  if (oStep.htmlId) {
  149
+    return tagName + '(:id, "' + oStep.htmlId + '").value.should == "' + oStep.value + '"'
  150
+  } else if (oStep.name) {
  151
+    return tagName + '(:name, "' + oStep.name + '").value.should == "' + oStep.value + '"'
  152
+  } else {
  153
+    return tagName + '(:id, "specify_id_here").value.should == "' + oStep.value + '"'
  154
+  }
  155
+}
  156
+
BIN  src/content/itest2.png
49  src/content/itest2recorder.css
... ...
@@ -0,0 +1,49 @@
  1
+
  2
+@import url("chrome://global/skin/");
  3
+@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
  4
+
  5
+tabpanels, tabpanel, textbox
  6
+{
  7
+    -moz-appearance: none !important;
  8
+    font-family: monospace !important;
  9
+    padding: 0 !important;
  10
+}
  11
+
  12
+treechildren::-moz-tree-row(selected) { background-color: #FFFFAA; }
  13
+treechildren::-moz-tree-row(odd) { background-color: #EEEEEE; }
  14
+treechildren::-moz-tree-row(odd, selected) { background-color: #FFFFAA; }
  15
+treechildren::-moz-tree-cell-text(selected) { color: #000000; }
  16
+treechildren::-moz-tree-cell-text(odd, selected) { color: #000000; }
  17
+
  18
+editor
  19
+{
  20
+	border: thin solid #000000;;
  21
+}
  22
+
  23
+#status_label {
  24
+    color: #0000Ff;
  25
+}
  26
+
  27
+toolbarbutton.icon {
  28
+  padding-left: 4px;
  29
+  padding-right: 4px;
  30
+}
  31
+
  32
+toolbarbutton.icon:not([disabled="true"]) { 
  33
+/*  list-style-image: url("icons.png");*/
  34
+   font-style: bold;
  35
+}
  36
+
  37
+toolbarbutton.icon[disabled="true"] { 
  38
+/*  list-style-image: url("icons_disabled.png");*/
  39
+	font-style: bold;
  40
+}
  41
+
  42
+#record-button:not([checked="true"]) { 
  43
+  list-style-image: url("record.png");
  44
+/*  -moz-image-region: rect(0px 48px 16px 32px);*/
  45
+}
  46
+#record-button[checked="true"] {