Skip to content

Commit

Permalink
Allow the htmlrunner to store variables
Browse files Browse the repository at this point in the history
  • Loading branch information
shs96c committed Jul 18, 2016
1 parent b1d30a5 commit 37cdce0
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
import com.thoughtworks.selenium.Selenium;

public interface CoreStep {
NextStepDecorator execute(Selenium selenium);
NextStepDecorator execute(Selenium selenium, TestState state);
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,12 @@ public void run(Results results, WebDriver driver, Selenium selenium) {
}

List<LoggableStep> steps = findCommands(driver);
TestState state = new TestState();
List<StepResult> testResults = new ArrayList<>(steps.size());
NextStepDecorator decorator = NextStepDecorator.IDENTITY;
for (LoggableStep step : steps) {
LOG.info(step.toString());
decorator = Preconditions.checkNotNull(decorator.evaluate(step, selenium), step);
decorator = Preconditions.checkNotNull(decorator.evaluate(step, selenium, state), step);
testResults.add(new StepResult(step, null));
if (!decorator.isOkayToContinueTest()) {
break;
Expand Down Expand Up @@ -113,8 +114,8 @@ public LoggableStep(CoreStep toWrap, String command, String locator, String valu
}

@Override
public NextStepDecorator execute(Selenium selenium) {
return actualStep.execute(selenium);
public NextStepDecorator execute(Selenium selenium, TestState state) {
return actualStep.execute(selenium, state);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ public boolean isOkayToContinueTest() {

public abstract boolean isOkayToContinueTest();

public NextStepDecorator evaluate(CoreStep nextStep, Selenium selenium) {
return nextStep.execute(selenium);
public NextStepDecorator evaluate(CoreStep nextStep, Selenium selenium, TestState state) {
return nextStep.execute(selenium, state);
}

public static NextStepDecorator ERROR(Throwable cause) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,36 +40,44 @@ public ImmutableMap<String, CoreStepFactory> get() {
private static ImmutableMap<String, CoreStepFactory> build() {
ImmutableMap.Builder<String, CoreStepFactory> steps = ImmutableMap.builder();

CoreStepFactory nextCommandFails = (locator, value) -> (selenium) -> new NextCommandFails();
CoreStepFactory nextCommandFails = (locator, value) ->
(selenium, state) -> new NextCommandFails();

steps.put("assertErrorOnNext", nextCommandFails);
steps.put("assertFailureOnNext", nextCommandFails);

steps.put("echo", ((locator, value) -> (selenium) -> {
steps.put("echo", ((locator, value) -> (selenium, state) -> {
LOG.info(locator);
return NextStepDecorator.IDENTITY;
}));

steps.put("pause", ((locator, value) -> (selenium) -> {
steps.put("pause", ((locator, value) -> (selenium, state) -> {
try {
long timeout = Long.parseLong(locator);
long timeout = Long.parseLong(state.expand(locator));
Thread.sleep(timeout);
return NextStepDecorator.IDENTITY;
} catch (NumberFormatException e) {
return NextStepDecorator.ERROR(
new SeleniumException("Unable to parse timeout: " + locator));
new SeleniumException("Unable to parse timeout: " + state.expand(locator)));
} catch (InterruptedException e) {
System.exit(255);
throw new CoreRunnerError("We never get this far");
}
}));

steps.put("store", (((locator, value) -> ((selenium, state) -> {
state.store(state.expand(locator), state.expand(value));
return null;
}))));

return steps.build();
}

private static class NextCommandFails extends NextStepDecorator {

@Override
public NextStepDecorator evaluate(CoreStep nextStep, Selenium selenium) {
NextStepDecorator actualResult = nextStep.execute(selenium);
public NextStepDecorator evaluate(CoreStep nextStep, Selenium selenium, TestState state) {
NextStepDecorator actualResult = nextStep.execute(selenium, state);

// This is kind of fragile. Oh well.
if (actualResult.equals(NextStepDecorator.IDENTITY)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ private static ImmutableMap<String, CoreStepFactory> discover() {
continue;
}

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

factories.put(method.getName(), factory);
Expand All @@ -77,20 +77,24 @@ private static ImmutableMap<String, CoreStepFactory> discover() {
// getFoo, assertFoo, verifyFoo, assertNotFoo, verifyNotFoo
// storeFoo, waitForFoo, and waitForNotFoo.
final String shortName;
boolean isAccessor;
if (method.getName().startsWith("get")) {
shortName = method.getName().substring("get".length());
isAccessor = true;
} else if (method.getName().startsWith("is")) {
shortName = method.getName().substring("is".length());
isAccessor = true;
} else {
shortName = null;
isAccessor = false;
}

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

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

try {
SeleneseTestBase.assertEquals(expected, seen);
Expand All @@ -100,7 +104,9 @@ private static ImmutableMap<String, CoreStepFactory> discover() {
}
}));

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

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

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

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

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

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

if (isAccessor) {
factories.put(
"store" + shortName,
((loc, val) -> (selenium, state) -> {
String locator = state.expand(loc);
String value = state.expand(val);
Object toStore = invokeMethod(method, selenium, buildArgs(method, locator, value));
state.store(locator, toStore);
return null;
}));
}

factories.put(
method.getName() + "AndWait",
((locator, value) -> (selenium -> {
Object result = invokeMethod(method, selenium, buildArgs(method, locator, value));
((locator, value) -> (selenium, state) -> {
invokeMethod(
method,
selenium,
buildArgs(method, state.expand(locator), state.expand(value)));
// TODO: Hard coding this is obviously bogus
selenium.waitForPageToLoad("30000");
return NextStepDecorator.IDENTITY;
})));
}));
}

return factories.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package org.openqa.selenium.server.htmlrunner;

import static java.util.regex.Pattern.MULTILINE;

import com.google.common.base.Preconditions;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class TestState {
private static Map<String, Object> storedValues = new HashMap<>();

public void store(String key, Object value) {
storedValues.put(key, value);
}

private String getValue(String key) {
return Preconditions.checkNotNull(key);
}

public String expand(String toExpand) {
/*
Selenium.prototype.replaceVariables = function(str) {
var stringResult = str;
// Find all of the matching variable references
var match = stringResult.match(/\$\{\w+\}/g);
if (!match) {
return stringResult;
}
// For each match, lookup the variable value, and replace if found
for (var i = 0; match && i < match.length; i++) {
var variable = match[i]; // The replacement variable, with ${}
var name = variable.substring(2, variable.length - 1); // The replacement variable without ${}
var replacement = storedVars[name];
if (replacement && typeof(replacement) === 'string' && replacement.indexOf('$') != -1) {
replacement = replacement.replace(/\$/g, '$$$$'); //double up on $'s because of the special meaning these have in 'replace'
}
if (replacement != undefined) {
stringResult = stringResult.replace(variable, replacement);
}
}
return stringResult;
};
*/
Pattern toMatch = Pattern.compile("\\$\\{(\\w+)\\}", MULTILINE);
Matcher matcher = toMatch.matcher(toExpand);
StringBuilder toReturn = new StringBuilder();

int lastEnd = 0;
while (matcher.find()) {
// Copy from the last end into the stringbuffer
toReturn.append(toExpand.substring(lastEnd, matcher.start()));
// Now insert the value
toReturn.append(getValue(matcher.group(1)));
lastEnd = matcher.end();
}

return toReturn.toString();
}
}
17 changes: 9 additions & 8 deletions java/server/test/org/openqa/selenium/tests/TestSuite.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
}
}
}

function isFileURL() {
var p = window.location.protocol;
var result = ("file:" == p);
Expand All @@ -61,12 +61,12 @@
<tr><td><a href="./TestUseXpathLibrary.html">TestUseXpathLibrary</a></td></tr>
<tr unless="browserVersion.isSafari" ><td><a href="./events/TestMouseEvents.html">TestMouseEvents</a></td></tr>
<tr><td><a href="./TestBrowserVersion.html">TestBrowserVersion</a></td></tr>

<tr><td><a href="./TestJavaScriptAttributes.html">TestJavaScriptAttributes</a></td></tr>

<tr unless="browserVersion.isKonqueror || browserVersion.isSafari"><td><a href="./events/TestKeyEvents.html">TestKeyEvents</a></td></tr>
<tr unless="browserVersion.isKonqueror || browserVersion.isSafari"><td><a href="./TestVisibility.html">TestVisibility</a></td></tr>

<tr><td><a href="./TestFramesOpen.html">TestFramesOpen</a></td></tr>
<tr><td><a href="./TestFramesNested.html">TestFramesNested</a></td></tr>
<tr><td><a href="./TestFramesClick.html">TestFramesClick</a></td></tr>
Expand All @@ -75,9 +75,10 @@
<tr><td><a href="./TestSelectMultiLevelFrame.html">TestSelectMultiLevelFrame</a></td></tr>
<tr><td><a href="./TestOpenInTargetFrame.html">TestOpenInTargetFrame</a></td></tr>

<tr unless="isFileURL()"><td><a href="./TestCookie.html">TestCookie</a></td></tr>
<!-- skipping because it relies on SeCore internals -->
<!--<tr unless="isFileURL()"><td><a href="./TestCookie.html">TestCookie</a></td></tr>-->
<tr><td><a href="./TestEval.html">TestEval</a></td></tr>

<tr><td><a href="./TestOpen.html">TestOpen</a></td></tr>
<tr><td><a href="./TestClick.html">TestClick</a></td></tr>
<tr><td><a href="./TestClickJavascriptHref.html">TestClickJavascriptHref</a></td></tr>
Expand All @@ -95,13 +96,13 @@
<tr><td><a href="./TestMultiSelect.html">TestMultiSelect</a></td></tr>
<tr><td><a href="./TestSubmit.html">TestSubmit</a></td></tr>
<tr><td><a href="./TestCheckUncheck.html">TestCheckUncheck</a></td></tr>

<tr><td><a href="./TestGet.html">TestGet</a></td></tr>
<tr><td><a href="./TestStore.html">TestStore</a></td></tr>
<tr><td><a href="./TestJavascriptParameters.html">TestJavascriptParameters</a></td></tr>
<tr><td><a href="./TestPause.html">TestPause</a></td></tr>
<tr><td><a href="./TestWait.html">TestWait</a></td></tr>

<tr><td><a href="./TestWaitFor.html">TestWaitFor</a></td></tr>
<tr><td><a href="./TestWaitForNot.html">TestWaitForNot</a></td></tr>
<tr><td><a href="./TestVerifications.html">TestVerifications</a></td></tr>
Expand Down

0 comments on commit 37cdce0

Please sign in to comment.