package jp.vmi.selenium.selenese;
import java.util.ArrayDeque;
import java.util.Deque;
import org.apache.commons.io.FilenameUtils;
import jp.vmi.html.result.IHtmlResultTestCase;
import jp.vmi.junit.result.ITestCase;
import jp.vmi.selenium.selenese.command.CommandList;
import jp.vmi.selenium.selenese.command.EndLoop;
import jp.vmi.selenium.selenese.command.ICommand;
import jp.vmi.selenium.selenese.command.ICommandFactory;
import jp.vmi.selenium.selenese.command.StartLoop;
import jp.vmi.selenium.selenese.inject.Binder;
import jp.vmi.selenium.selenese.inject.ExecuteTestCase;
import jp.vmi.selenium.selenese.result.CommandResultList;
import jp.vmi.selenium.selenese.result.Result;
import jp.vmi.selenium.selenese.utils.LogRecorder;
import jp.vmi.selenium.selenese.utils.PathUtils;
import jp.vmi.selenium.selenese.utils.StopWatch;
import static jp.vmi.selenium.selenese.command.StartLoop.*;
import static jp.vmi.selenium.selenese.result.Success.*;
/**
* test-case object for execution.
* <p>
* Supports Selenium IDE flow control plugin.
* </p>
* @see <a href="https://github.com/davehunt/selenium-ide-flowcontrol">A flow control plugin for Selenium IDE</a>
*/
public class TestCase implements Selenese, ITestCase, IHtmlResultTestCase {
private String filename = null;
private String baseName = null;
private String name = null;
private String baseURL = null;
private StartLoop currentStartLoop = NO_START_LOOP;
private final Deque<StartLoop> loopCommandStack = new ArrayDeque<>();
private final CommandList commandList = Binder.newCommandList();
private final CommandResultList cresultList = new CommandResultList();
private final StopWatch stopWatch = new StopWatch();
private LogRecorder logRecorder = null;
/**
* Initialize after constructed.
*
* @param filename selenese script filename. (This base name is used for generating screenshot file)
* @param name test-case name.
* @param baseURL effective base URL.
* @return this.
*/
public TestCase initialize(String filename, String name, String baseURL) {
filename = PathUtils.normalize(filename);
String baseName = filename != null ? FilenameUtils.getBaseName(filename) : name;
if (name == null)
name = baseName;
this.filename = filename;
this.baseName = baseName;
this.name = name;
this.baseURL = baseURL.replaceFirst("/+$", ""); // remove trailing "/".
return this;
}
@Override
public Type getType() {
return Type.TEST_CASE;
}
@Override
public boolean isError() {
return false;
}
/**
* Get filename of test-case.
*
* @return filename.
*/
@Override
public String getFilename() {
return filename;
}
@Override
public String getBaseName() {
return baseName;
}
@Override
public String getName() {
return name;
}
/**
* Get base URL in the test-case.
*
* @return base URL.
*/
public String getBaseURL() {
return baseURL;
}
/**
* Get command list.
*
* @return command list.
*/
@Override
public CommandList getCommandList() {
return commandList;
}
/**
* Get stop watch.
*
* @return stop watch.
*/
@Override
public StopWatch getStopWatch() {
return stopWatch;
}
@Override
public void setLogRecorder(LogRecorder logRecorder) {
if (this.logRecorder != null)
throw new SeleneseRunnerRuntimeException("The log recorder of " + this + " is already set.");
this.logRecorder = logRecorder;
}
@Override
public LogRecorder getLogRecorder() {
return logRecorder;
}
@Override
public Result getResult() {
return cresultList.getResult();
}
/**
* Get test-case result list.
*
* @return test-case result list.
*/
@Override
public CommandResultList getResultList() {
return cresultList;
}
/**
* Add command to command list.
*
* @param command command.
*/
public void addCommand(ICommand command) {
command.setStartLoop(currentStartLoop);
if (command instanceof StartLoop) {
loopCommandStack.push(currentStartLoop);
currentStartLoop = (StartLoop) command;
} else if (command instanceof EndLoop) {
currentStartLoop.setEndLoop((EndLoop) command);
currentStartLoop = loopCommandStack.pop();
}
commandList.add(command);
}
/**
* Add command to command list.
*
* @param commandFactory command factory.
* @param name command name.
* @param args command arguments.
*/
public void addCommand(ICommandFactory commandFactory, String name, String... args) {
int i = commandList.size() + 1;
ICommand command = commandFactory.newCommand(i, name, args);
addCommand(command);
}
@ExecuteTestCase
@Override
public Result execute(Selenese parent, Context context) {
if (commandList.isEmpty())
return cresultList.setResult(SUCCESS);
if (parent instanceof TestCase) {
try {
context.setCurrentTestCase(this);
return commandList.execute(context, ((TestCase) parent).getResultList());
} finally {
context.setCurrentTestCase((TestCase) parent);
}
} else {
context.setCurrentTestCase(this);
context.resetState();
cresultList.setEndTime(System.currentTimeMillis());
return commandList.execute(context, cresultList);
}
}
@Override
public String toString() {
StringBuilder s = new StringBuilder("TestCase[").append(name).append("]");
if (filename != null)
s.append(" (").append(filename).append(")");
return s.toString();
}
}