Skip to content

Commit 37cdce0

Browse files
committed
Allow the htmlrunner to store variables
1 parent b1d30a5 commit 37cdce0

File tree

7 files changed

+149
-30
lines changed

7 files changed

+149
-30
lines changed

java/server/src/org/openqa/selenium/server/htmlrunner/CoreStep.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@
2020
import com.thoughtworks.selenium.Selenium;
2121

2222
public interface CoreStep {
23-
NextStepDecorator execute(Selenium selenium);
23+
NextStepDecorator execute(Selenium selenium, TestState state);
2424
}

java/server/src/org/openqa/selenium/server/htmlrunner/CoreTestCase.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,12 @@ public void run(Results results, WebDriver driver, Selenium selenium) {
5555
}
5656

5757
List<LoggableStep> steps = findCommands(driver);
58+
TestState state = new TestState();
5859
List<StepResult> testResults = new ArrayList<>(steps.size());
5960
NextStepDecorator decorator = NextStepDecorator.IDENTITY;
6061
for (LoggableStep step : steps) {
6162
LOG.info(step.toString());
62-
decorator = Preconditions.checkNotNull(decorator.evaluate(step, selenium), step);
63+
decorator = Preconditions.checkNotNull(decorator.evaluate(step, selenium, state), step);
6364
testResults.add(new StepResult(step, null));
6465
if (!decorator.isOkayToContinueTest()) {
6566
break;
@@ -113,8 +114,8 @@ public LoggableStep(CoreStep toWrap, String command, String locator, String valu
113114
}
114115

115116
@Override
116-
public NextStepDecorator execute(Selenium selenium) {
117-
return actualStep.execute(selenium);
117+
public NextStepDecorator execute(Selenium selenium, TestState state) {
118+
return actualStep.execute(selenium, state);
118119
}
119120

120121
@Override

java/server/src/org/openqa/selenium/server/htmlrunner/NextStepDecorator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ public boolean isOkayToContinueTest() {
4848

4949
public abstract boolean isOkayToContinueTest();
5050

51-
public NextStepDecorator evaluate(CoreStep nextStep, Selenium selenium) {
52-
return nextStep.execute(selenium);
51+
public NextStepDecorator evaluate(CoreStep nextStep, Selenium selenium, TestState state) {
52+
return nextStep.execute(selenium, state);
5353
}
5454

5555
public static NextStepDecorator ERROR(Throwable cause) {

java/server/src/org/openqa/selenium/server/htmlrunner/NonReflectiveSteps.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,36 +40,44 @@ public ImmutableMap<String, CoreStepFactory> get() {
4040
private static ImmutableMap<String, CoreStepFactory> build() {
4141
ImmutableMap.Builder<String, CoreStepFactory> steps = ImmutableMap.builder();
4242

43-
CoreStepFactory nextCommandFails = (locator, value) -> (selenium) -> new NextCommandFails();
43+
CoreStepFactory nextCommandFails = (locator, value) ->
44+
(selenium, state) -> new NextCommandFails();
45+
4446
steps.put("assertErrorOnNext", nextCommandFails);
4547
steps.put("assertFailureOnNext", nextCommandFails);
4648

47-
steps.put("echo", ((locator, value) -> (selenium) -> {
49+
steps.put("echo", ((locator, value) -> (selenium, state) -> {
4850
LOG.info(locator);
4951
return NextStepDecorator.IDENTITY;
5052
}));
5153

52-
steps.put("pause", ((locator, value) -> (selenium) -> {
54+
steps.put("pause", ((locator, value) -> (selenium, state) -> {
5355
try {
54-
long timeout = Long.parseLong(locator);
56+
long timeout = Long.parseLong(state.expand(locator));
5557
Thread.sleep(timeout);
5658
return NextStepDecorator.IDENTITY;
5759
} catch (NumberFormatException e) {
5860
return NextStepDecorator.ERROR(
59-
new SeleniumException("Unable to parse timeout: " + locator));
61+
new SeleniumException("Unable to parse timeout: " + state.expand(locator)));
6062
} catch (InterruptedException e) {
6163
System.exit(255);
6264
throw new CoreRunnerError("We never get this far");
6365
}
6466
}));
67+
68+
steps.put("store", (((locator, value) -> ((selenium, state) -> {
69+
state.store(state.expand(locator), state.expand(value));
70+
return null;
71+
}))));
72+
6573
return steps.build();
6674
}
6775

6876
private static class NextCommandFails extends NextStepDecorator {
6977

7078
@Override
71-
public NextStepDecorator evaluate(CoreStep nextStep, Selenium selenium) {
72-
NextStepDecorator actualResult = nextStep.execute(selenium);
79+
public NextStepDecorator evaluate(CoreStep nextStep, Selenium selenium, TestState state) {
80+
NextStepDecorator actualResult = nextStep.execute(selenium, state);
7381

7482
// This is kind of fragile. Oh well.
7583
if (actualResult.equals(NextStepDecorator.IDENTITY)) {

java/server/src/org/openqa/selenium/server/htmlrunner/ReflectivelyDiscoveredSteps.java

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ private static ImmutableMap<String, CoreStepFactory> discover() {
6868
continue;
6969
}
7070

71-
CoreStepFactory factory = ((locator, value) -> (selenium) ->
71+
CoreStepFactory factory = ((locator, value) -> (selenium, state) ->
7272
invokeMethod(method, selenium, buildArgs(method, locator, value)));
7373

7474
factories.put(method.getName(), factory);
@@ -77,20 +77,24 @@ private static ImmutableMap<String, CoreStepFactory> discover() {
7777
// getFoo, assertFoo, verifyFoo, assertNotFoo, verifyNotFoo
7878
// storeFoo, waitForFoo, and waitForNotFoo.
7979
final String shortName;
80+
boolean isAccessor;
8081
if (method.getName().startsWith("get")) {
8182
shortName = method.getName().substring("get".length());
83+
isAccessor = true;
8284
} else if (method.getName().startsWith("is")) {
8385
shortName = method.getName().substring("is".length());
86+
isAccessor = true;
8487
} else {
8588
shortName = null;
89+
isAccessor = false;
8690
}
8791

8892
if (shortName != null && method.getParameterCount() < 2) {
8993
String negatedName = negateName(shortName);
9094

91-
factories.put("assert" + shortName, ((locator, value) -> (selenium) -> {
95+
factories.put("assert" + shortName, ((locator, value) -> (selenium, state) -> {
9296
Object seen = invokeMethod(method, selenium, buildArgs(method, locator, value));
93-
String expected = getExpectedValue(method, locator, value);
97+
String expected = getExpectedValue(method, state.expand(locator), state.expand(value));
9498

9599
try {
96100
SeleneseTestBase.assertEquals(expected, seen);
@@ -100,7 +104,9 @@ private static ImmutableMap<String, CoreStepFactory> discover() {
100104
}
101105
}));
102106

103-
factories.put("assert" + negatedName, ((locator, value) -> (selenium) -> {
107+
factories.put("assert" + negatedName, ((loc, val) -> (selenium, state) -> {
108+
String locator = state.expand(loc);
109+
String value = state.expand(val);
104110
Object seen = invokeMethod(method, selenium, buildArgs(method, locator, value));
105111
String expected = getExpectedValue(method, locator, value);
106112

@@ -112,7 +118,9 @@ private static ImmutableMap<String, CoreStepFactory> discover() {
112118
}
113119
}));
114120

115-
factories.put("verify" + shortName, ((locator, value) -> (selenium) -> {
121+
factories.put("verify" + shortName, ((loc, val) -> (selenium, state) -> {
122+
String locator = state.expand(loc);
123+
String value = state.expand(val);
116124
Object seen = invokeMethod(method, selenium, buildArgs(method, locator, value));
117125
String expected = getExpectedValue(method, locator, value);
118126

@@ -124,7 +132,9 @@ private static ImmutableMap<String, CoreStepFactory> discover() {
124132
}
125133
}));
126134

127-
factories.put("verify" + negatedName, ((locator, value) -> (selenium) -> {
135+
factories.put("verify" + negatedName, ((loc, val) -> (selenium, state) -> {
136+
String locator = state.expand(loc);
137+
String value = state.expand(val);
128138
Object seen = invokeMethod(method, selenium, buildArgs(method, locator, value));
129139
String expected = getExpectedValue(method, locator, value);
130140

@@ -137,14 +147,29 @@ private static ImmutableMap<String, CoreStepFactory> discover() {
137147
}));
138148
}
139149

150+
if (isAccessor) {
151+
factories.put(
152+
"store" + shortName,
153+
((loc, val) -> (selenium, state) -> {
154+
String locator = state.expand(loc);
155+
String value = state.expand(val);
156+
Object toStore = invokeMethod(method, selenium, buildArgs(method, locator, value));
157+
state.store(locator, toStore);
158+
return null;
159+
}));
160+
}
161+
140162
factories.put(
141163
method.getName() + "AndWait",
142-
((locator, value) -> (selenium -> {
143-
Object result = invokeMethod(method, selenium, buildArgs(method, locator, value));
164+
((locator, value) -> (selenium, state) -> {
165+
invokeMethod(
166+
method,
167+
selenium,
168+
buildArgs(method, state.expand(locator), state.expand(value)));
144169
// TODO: Hard coding this is obviously bogus
145170
selenium.waitForPageToLoad("30000");
146171
return NextStepDecorator.IDENTITY;
147-
})));
172+
}));
148173
}
149174

150175
return factories.build();
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.server.htmlrunner;
19+
20+
import static java.util.regex.Pattern.MULTILINE;
21+
22+
import com.google.common.base.Preconditions;
23+
24+
import java.util.HashMap;
25+
import java.util.Map;
26+
import java.util.regex.Matcher;
27+
import java.util.regex.Pattern;
28+
29+
class TestState {
30+
private static Map<String, Object> storedValues = new HashMap<>();
31+
32+
public void store(String key, Object value) {
33+
storedValues.put(key, value);
34+
}
35+
36+
private String getValue(String key) {
37+
return Preconditions.checkNotNull(key);
38+
}
39+
40+
public String expand(String toExpand) {
41+
/*
42+
43+
Selenium.prototype.replaceVariables = function(str) {
44+
var stringResult = str;
45+
46+
// Find all of the matching variable references
47+
var match = stringResult.match(/\$\{\w+\}/g);
48+
if (!match) {
49+
return stringResult;
50+
}
51+
52+
// For each match, lookup the variable value, and replace if found
53+
for (var i = 0; match && i < match.length; i++) {
54+
var variable = match[i]; // The replacement variable, with ${}
55+
var name = variable.substring(2, variable.length - 1); // The replacement variable without ${}
56+
var replacement = storedVars[name];
57+
if (replacement && typeof(replacement) === 'string' && replacement.indexOf('$') != -1) {
58+
replacement = replacement.replace(/\$/g, '$$$$'); //double up on $'s because of the special meaning these have in 'replace'
59+
}
60+
if (replacement != undefined) {
61+
stringResult = stringResult.replace(variable, replacement);
62+
}
63+
}
64+
return stringResult;
65+
};
66+
67+
68+
*/
69+
Pattern toMatch = Pattern.compile("\\$\\{(\\w+)\\}", MULTILINE);
70+
Matcher matcher = toMatch.matcher(toExpand);
71+
StringBuilder toReturn = new StringBuilder();
72+
73+
int lastEnd = 0;
74+
while (matcher.find()) {
75+
// Copy from the last end into the stringbuffer
76+
toReturn.append(toExpand.substring(lastEnd, matcher.start()));
77+
// Now insert the value
78+
toReturn.append(getValue(matcher.group(1)));
79+
lastEnd = matcher.end();
80+
}
81+
82+
return toReturn.toString();
83+
}
84+
}

java/server/test/org/openqa/selenium/tests/TestSuite.html

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
}
4242
}
4343
}
44-
44+
4545
function isFileURL() {
4646
var p = window.location.protocol;
4747
var result = ("file:" == p);
@@ -61,12 +61,12 @@
6161
<tr><td><a href="./TestUseXpathLibrary.html">TestUseXpathLibrary</a></td></tr>
6262
<tr unless="browserVersion.isSafari" ><td><a href="./events/TestMouseEvents.html">TestMouseEvents</a></td></tr>
6363
<tr><td><a href="./TestBrowserVersion.html">TestBrowserVersion</a></td></tr>
64-
64+
6565
<tr><td><a href="./TestJavaScriptAttributes.html">TestJavaScriptAttributes</a></td></tr>
66-
66+
6767
<tr unless="browserVersion.isKonqueror || browserVersion.isSafari"><td><a href="./events/TestKeyEvents.html">TestKeyEvents</a></td></tr>
6868
<tr unless="browserVersion.isKonqueror || browserVersion.isSafari"><td><a href="./TestVisibility.html">TestVisibility</a></td></tr>
69-
69+
7070
<tr><td><a href="./TestFramesOpen.html">TestFramesOpen</a></td></tr>
7171
<tr><td><a href="./TestFramesNested.html">TestFramesNested</a></td></tr>
7272
<tr><td><a href="./TestFramesClick.html">TestFramesClick</a></td></tr>
@@ -75,9 +75,10 @@
7575
<tr><td><a href="./TestSelectMultiLevelFrame.html">TestSelectMultiLevelFrame</a></td></tr>
7676
<tr><td><a href="./TestOpenInTargetFrame.html">TestOpenInTargetFrame</a></td></tr>
7777

78-
<tr unless="isFileURL()"><td><a href="./TestCookie.html">TestCookie</a></td></tr>
78+
<!-- skipping because it relies on SeCore internals -->
79+
<!--<tr unless="isFileURL()"><td><a href="./TestCookie.html">TestCookie</a></td></tr>-->
7980
<tr><td><a href="./TestEval.html">TestEval</a></td></tr>
80-
81+
8182
<tr><td><a href="./TestOpen.html">TestOpen</a></td></tr>
8283
<tr><td><a href="./TestClick.html">TestClick</a></td></tr>
8384
<tr><td><a href="./TestClickJavascriptHref.html">TestClickJavascriptHref</a></td></tr>
@@ -95,13 +96,13 @@
9596
<tr><td><a href="./TestMultiSelect.html">TestMultiSelect</a></td></tr>
9697
<tr><td><a href="./TestSubmit.html">TestSubmit</a></td></tr>
9798
<tr><td><a href="./TestCheckUncheck.html">TestCheckUncheck</a></td></tr>
98-
99+
99100
<tr><td><a href="./TestGet.html">TestGet</a></td></tr>
100101
<tr><td><a href="./TestStore.html">TestStore</a></td></tr>
101102
<tr><td><a href="./TestJavascriptParameters.html">TestJavascriptParameters</a></td></tr>
102103
<tr><td><a href="./TestPause.html">TestPause</a></td></tr>
103104
<tr><td><a href="./TestWait.html">TestWait</a></td></tr>
104-
105+
105106
<tr><td><a href="./TestWaitFor.html">TestWaitFor</a></td></tr>
106107
<tr><td><a href="./TestWaitForNot.html">TestWaitForNot</a></td></tr>
107108
<tr><td><a href="./TestVerifications.html">TestVerifications</a></td></tr>

0 commit comments

Comments
 (0)