@@ -17,269 +17,17 @@

public class WhenFormattingScreenshotDetailsForHtml {

@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();

@Test
public void the_test_step_has_a_description() {
TestStep step = new TestStep("a narrative description");
assertThat(step.getDescription(), is("a narrative description"));
}

@Test
public void the_test_step_can_have_an_illustration() throws IOException {
TestStep step = new TestStep("a narrative description");

File screenshot = temporaryFolder.newFile("screenshot.png");
File source = temporaryFolder.newFile("screenshot.html");
step.addScreenshot(new ScreenshotAndHtmlSource(screenshot, source));

assertThat(step.getScreenshots().get(0).getScreenshotFile(), is(screenshot));
assertThat(step.getScreenshots().get(0).getSourcecode(), is(source));
}

@Test
public void the_test_step_can_have_more_than_one_illustration() throws IOException {
TestStep step = new TestStep("a narrative description");

step.addScreenshot(forScreenshotWithImage("/screenshots/google_page_1.png").and().withSource("screenshot.html"));
step.addScreenshot(forScreenshotWithImage("/screenshots/google_page_2.png").and().withSource("screenshot2.html"));

ScreenshotAndHtmlSource screenshot1 = step.getScreenshots().get(0);
ScreenshotAndHtmlSource screenshot2 = step.getScreenshots().get(1);

assertThat(screenshot1.getScreenshotFile().getName(), is("google_page_1.png"));
assertThat(screenshot1.getSourcecode().getName(), is("screenshot.html"));

assertThat(screenshot2.getScreenshotFile().getName(), is("google_page_2.png"));
assertThat(screenshot2.getSourcecode().getName(), is("screenshot2.html"));

assertThat(screenshot1.hashCode(), is(not(screenshot2.hashCode())));
public void quotes_should_be_presented_as_entities() {
Screenshot screenshot = new Screenshot("file.png", "Login with user \"bill\"",1000);
assertThat(screenshot.getHtml().getDescription(), is("Login with user "bill""));
}

@Test
public void the_test_step_knows_how_many_illustrations_it_has() throws IOException {
TestStep step = new TestStep("a narrative description");

step.addScreenshot(forScreenshotWithImage("/screenshots/google_page_1.png").and().withSource("screenshot.html"));
step.addScreenshot(forScreenshotWithImage("/screenshots/google_page_2.png").and().withSource("screenshot2.html"));
step.addScreenshot(forScreenshotWithImage("/screenshots/google_page_3.png").and().withSource("screenshot2.html"));

assertThat(step.getScreenshotCount(), is(3));
}

private ScreenshotAndHtmlSourceBuilder forScreenshotWithImage(String image) {
return new ScreenshotAndHtmlSourceBuilder().withImage(image);
}

private class ScreenshotAndHtmlSourceBuilder {
String image;
public ScreenshotAndHtmlSourceBuilder withImage(String image) {
this.image = image;
return this;
}

public ScreenshotAndHtmlSourceBuilder and() {
return this;
}

public ScreenshotAndHtmlSource withSource(String source) throws IOException {
File screenshotFile = screenshotFileFrom(image);
File sourceFile = new File(source);
return new ScreenshotAndHtmlSource(screenshotFile, sourceFile);
}


public void non_ascii_chars_should_be_excluded() {
Screenshot screenshot = new Screenshot("file.png", "Login with user \"bill\"",1000);
assertThat(screenshot.getHtml().getDescription(), is("Login with user "bill""));
}

@Test
public void the_first_screenshot_can_be_used_to_represent_the_step() throws IOException {
TestStep step = new TestStep("a narrative description");

File screenshot = temporaryFolder.newFile("screenshot.png");
File source = temporaryFolder.newFile("screenshot.html");
step.addScreenshot(new ScreenshotAndHtmlSource(screenshot, source));

File screenshot2 = temporaryFolder.newFile("screenshot2.png");
File source2 = temporaryFolder.newFile("screenshot2.html");
step.addScreenshot(new ScreenshotAndHtmlSource(screenshot2, source2));

assertThat(step.getFirstScreenshot().getScreenshotFile(), is(screenshot));
assertThat(step.getFirstScreenshot().getSourcecode(), is(source));
}

@Test
public void if_a_screenshot_is_identical_to_the_previous_one_in_the_step_it_wont_be_added() throws IOException {
TestStep step = new TestStep("a narrative description");

File screenshot = temporaryFolder.newFile("screenshot.png");
File source = temporaryFolder.newFile("screenshot.html");
step.addScreenshot(new ScreenshotAndHtmlSource(screenshot, source));
step.addScreenshot(new ScreenshotAndHtmlSource(screenshot, source));

assertThat(step.getScreenshots().size(), is(1));
}

@Test
public void the_first_screenshot_is_null_if_there_are_no_screenshots() throws IOException {
TestStep step = new TestStep("a narrative description");

assertThat(step.getFirstScreenshot(), is(nullValue()));
}
@Test
public void when_a_step_fails_the_error_message_can_be_recorded() throws IOException {
TestStep step = new TestStep("a narrative description");

step.setResult(TestResult.FAILURE);
Exception e = new IllegalStateException();
step.failedWith(new Exception("Oh nose!"));
assertThat(step.getErrorMessage(), is("Oh nose!"));
}

@Test
public void when_a_step_fails_the_stack_trace_is_also_recorded() throws IOException {
TestStep step = new TestStep("a narrative description");

step.setResult(TestResult.FAILURE);
Throwable e = new IllegalStateException();
step.failedWith(new Exception("Oh nose", e));
assertThat(step.getException().getCause(), is(e));
}

@Test
public void when_a_step_fails_with_a_cause_the_original_message_is_used() throws IOException {
TestStep step = new TestStep("a narrative description");

step.setResult(TestResult.FAILURE);
Throwable e = new IllegalStateException("Original error");
step.failedWith(new Exception("Oh nose", e));
assertThat(step.getErrorMessage(), is("Original error"));
}

@Test
public void the_default_short_error_message_is_the_normal_error_message() throws IOException {
TestStep step = new TestStep("a narrative description");

step.setResult(TestResult.FAILURE);
Throwable e = new IllegalStateException("Original error");
step.failedWith(new Exception("Oh nose", e));
assertThat(step.getShortErrorMessage(), is("Original error"));
}

@Test
public void the_short_error_message_should_only_include_the_first_line() throws IOException {
TestStep step = new TestStep("a narrative description");

step.setResult(TestResult.FAILURE);
Throwable e = new IllegalStateException("Original error\nwith lots of messy details");
step.failedWith(new Exception("Oh nose", e));
assertThat(step.getShortErrorMessage(), is("Original error"));
}

@Test
public void the_short_error_message_should_replace_double_quotes_with_single_quotes() throws IOException {
TestStep step = new TestStep("a narrative description");

step.setResult(TestResult.FAILURE);
Throwable e = new IllegalStateException("Original \"error\"\nwith lots of messy details");
step.failedWith(new Exception("Oh nose", e));
assertThat(step.getShortErrorMessage(), is("Original 'error'"));
}

@Test
public void the_short_error_message_should_remove_double_quotes() throws IOException {
TestStep step = new TestStep("a narrative description");

step.setResult(TestResult.FAILURE);
Throwable e = new IllegalStateException("Original error");
step.failedWith(new Exception("Oh nose", e));
assertThat(step.getShortErrorMessage(), is("Original error"));
}

@Test
public void we_can_record_the_lifetime_of_a_test_step() throws InterruptedException {
TestStep step = new TestStep("a narrative description");
Thread.sleep(10);
step.recordDuration();
assertThat(step.getDuration(), is(greaterThanOrEqualTo(10L)));
}

@Test
public void a_test_result_can_be_defined_for_a_step() throws InterruptedException {
TestStep step = new TestStep("a narrative description");
step.setResult(TestResult.SUCCESS);

assertThat(step.getResult(), is(TestResult.SUCCESS));
}

@Test
public void a_test_step_with_empty_child_steps_is_pending() throws InterruptedException {
TestStep step = new TestStep("a narrative description");
step.addChildStep(new TestStep("child step 1"));
step.addChildStep(new TestStep("child step 2"));
step.addChildStep(new TestStep("child step 3"));

assertThat(step.getResult(), is(TestResult.PENDING));
}

@Test
public void an_empty_step_is_pending() throws InterruptedException {
TestStep step = new TestStep("a narrative description");
assertThat(step.getResult(), is(TestResult.PENDING));
}

@Test
public void a_test_step_with_successful_child_steps_is_successful() throws InterruptedException {
TestStep step = new TestStep("a narrative description");
step.addChildStep(successfulTestStepCalled("child step 1"));
step.addChildStep(successfulTestStepCalled("child step 2"));
step.addChildStep(successfulTestStepCalled("child step 3"));

assertThat(step.getResult(), is(TestResult.SUCCESS));
}

@Test
public void an_ignored_test_step_with_successful_child_steps_is_still_ignored() throws InterruptedException {
TestStep step = new TestStep("a narrative description");
step.setResult(TestResult.IGNORED);
step.addChildStep(successfulTestStepCalled("child step 1"));
step.addChildStep(successfulTestStepCalled("child step 2"));
step.addChildStep(successfulTestStepCalled("child step 3"));

assertThat(step.getResult(), is(TestResult.IGNORED));
}

@Test
public void a_skipped_test_step_with_successful_child_steps_is_still_ignored() throws InterruptedException {
TestStep step = new TestStep("a narrative description");
step.setResult(TestResult.SKIPPED);
step.addChildStep(successfulTestStepCalled("child step 1"));
step.addChildStep(successfulTestStepCalled("child step 2"));
step.addChildStep(successfulTestStepCalled("child step 3"));

assertThat(step.getResult(), is(TestResult.SKIPPED));
}

@Test
public void a_pending_test_step_with_successful_child_steps_is_still_pending() throws InterruptedException {
TestStep step = new TestStep("a narrative description");
step.setResult(TestResult.PENDING);
step.addChildStep(successfulTestStepCalled("child step 1"));
step.addChildStep(successfulTestStepCalled("child step 2"));
step.addChildStep(successfulTestStepCalled("child step 3"));

assertThat(step.getResult(), is(TestResult.PENDING));
}


private TestStep successfulTestStepCalled(String stepName) {
TestStep step = new TestStep(stepName);
step.setResult(TestResult.SUCCESS);
return step;
}

private File screenshotFileFrom(final String screenshot) {
URL sourcePath = getClass().getResource(screenshot);
return new File(sourcePath.getPath());
}
}
@@ -412,6 +412,53 @@ public void waitTilPageIsFullyLoaded() {
}
}


@DefaultUrl("http://localhost:8080/myapp/somepage")
final class PageObjectWithLongDefaultUrl extends PageObject {

public boolean pageFullyLoaded;

public PageObjectWithLongDefaultUrl(WebDriver driver) {
super(driver);
}
}

@Test
public void should_override_base_urls() {
PageObject page = new PageObjectWithLongDefaultUrl(webdriver);
PageUrls pageUrls = new PageUrls(page, configuration);
page.setPageUrls(pageUrls);

environmentVariables.setProperty("webdriver.base.url","http://prod.server");
page.open();

verify(webdriver).get("http://prod.server/myapp/somepage");
}

@Test
public void should_not_override_base_url_if_empty() {
PageObject page = new PageObjectWithLongDefaultUrl(webdriver);
PageUrls pageUrls = new PageUrls(page, configuration);
page.setPageUrls(pageUrls);

environmentVariables.clearProperty("webdriver.base.url");
page.open();

verify(webdriver).get("http://localhost:8080/myapp/somepage");
}

@Test
public void should_not_override_base_url_if_empty_string() {
PageObject page = new PageObjectWithLongDefaultUrl(webdriver);
PageUrls pageUrls = new PageUrls(page, configuration);
page.setPageUrls(pageUrls);

environmentVariables.setProperty("webdriver.base.url","");
page.open();

verify(webdriver).get("http://localhost:8080/myapp/somepage");
}

@Test
public void annotated_OnOpenPage_methods_should_be_called_when_the_page_is_opened() {
PageObjectWithOnOpenPageMethod page = new PageObjectWithOnOpenPageMethod(webdriver);
@@ -9,6 +9,7 @@
import net.thucydides.core.steps.ScenarioSteps;
import org.junit.Ignore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.ContextConfiguration;

@ContextConfiguration(locations = "/spring/config.xml")
@@ -57,6 +57,21 @@ public void the_output_directory_can_be_defined_in_a_system_property() {
assertThat(configuration.getUseUniqueBrowser(), is(true));
}

@Test
public void system_properties_cannot_be_set_if_defined() {
environmentVariables.setProperty("thucydides.use.unique.browser","true");
configuration.setIfUndefined("thucydides.use.unique.browser", "false");

assertThat(configuration.getUseUniqueBrowser(), is(true));
}

@Test
public void system_properties_can_be_set_if_undefined() {
configuration.setIfUndefined("thucydides.use.unique.browser", "false");

assertThat(configuration.getUseUniqueBrowser(), is(false));
}

@Test
public void the_default_unique_browser_value_should_be_false() {
assertThat(configuration.getUseUniqueBrowser(), is(false));
@@ -100,6 +100,51 @@ public void a_firefox_webdriver_instance_is_created_by_default_if_no_webdriver_s
assertThat(driver.proxiedWebDriver, instanceOf(FirefoxDriver.class));
}

@Test
public void if_an_empty_driver_type_is_specified_the_default_driver_should_be_used() {

WebDriverFacade defaultDriver = (WebDriverFacade) webdriverManager.getWebdriver();
WebDriverFacade driver = (WebDriverFacade) webdriverManager.getWebdriver("");

assertThat(driver, is(defaultDriver));
}

@Test
public void if_a_null_driver_type_is_specified_the_default_driver_should_be_used() {

WebDriverFacade defaultDriver = (WebDriverFacade) webdriverManager.getWebdriver();
WebDriverFacade driver = (WebDriverFacade) webdriverManager.getWebdriver(null);

assertThat(driver, is(defaultDriver));
}

@Test
public void the_default_driver_should_be_the_firefox_driver() {

WebDriverFacade defaultDriver = (WebDriverFacade) webdriverManager.getWebdriver();
WebDriverFacade firefoxDriver = (WebDriverFacade) webdriverManager.getWebdriver("firefox");

assertThat(firefoxDriver, is(defaultDriver));
}

@Test
public void driver_names_should_be_case_insensitive() {

WebDriverFacade uppercaseFirefoxDriver = (WebDriverFacade) webdriverManager.getWebdriver("Firefox");
WebDriverFacade firefoxDriver = (WebDriverFacade) webdriverManager.getWebdriver("firefox");

assertThat(firefoxDriver, is(uppercaseFirefoxDriver));
}

@Test
public void driver_names_for_non_default_drivers_should_be_case_insensitive() {

WebDriverFacade uppercaseFirefoxDriver = (WebDriverFacade) webdriverManager.getWebdriver("HtmlUnit");
WebDriverFacade firefoxDriver = (WebDriverFacade) webdriverManager.getWebdriver("htmlunit");

assertThat(firefoxDriver, is(uppercaseFirefoxDriver));
}

@Test
public void a_new_firefox_webdriver_instance_is_created_when_the_webdriver_system_property_is_set_to_firefox() {

@@ -1,7 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

<beans>
<bean id="widgetService" class="net.thucydides.core.steps.samples.WidgetService">
<property name="name"><value>Widgets</value></property>
<property name="quota"><value>1</value></property>
@@ -143,7 +143,7 @@
<div class="slider-wrapper theme-default">
<div id="slider">
<#foreach screenshot in screenshots>
<img src="${screenshot.filename}" alt="${screenshot.shortErrorMessage}" title="${screenshot.description}" width="${screenshot.width?string.computer}"/>
<img src="${screenshot.filename}" alt="${screenshot.shortErrorMessage}" title="${screenshot.html.description}" width="${screenshot.width?string.computer}"/>
</#foreach>
</div>
</div>