Skip to content

Commit

Permalink
Release 1.9-RC2
Browse files Browse the repository at this point in the history
* BasePage.findImage now returns an implementation of WebElement
* Some improvements and fixes in the visual testing demos
* Updated to Cucumber 6 (6.7.0)
* Updated (almost) all libraries
* Improved the quickstart archetype
* Updated the documentation
* Use Cucumber reporting instead of Cluecumber plugin
  • Loading branch information
martinschneider authored Sep 22, 2020
1 parent 78aa9c4 commit 5690a31
Show file tree
Hide file tree
Showing 46 changed files with 473 additions and 217 deletions.
2 changes: 1 addition & 1 deletion justtestlah-applitools/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<parent>
<groupId>qa.justtestlah</groupId>
<artifactId>justtestlah-parent</artifactId>
<version>1.9-RC1</version>
<version>1.9-RC2</version>
</parent>
<licenses>
<license>
Expand Down
2 changes: 1 addition & 1 deletion justtestlah-awsdevicefarm/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<parent>
<groupId>qa.justtestlah</groupId>
<artifactId>justtestlah-parent</artifactId>
<version>1.9-RC1</version>
<version>1.9-RC2</version>
</parent>
<licenses>
<license>
Expand Down
2 changes: 1 addition & 1 deletion justtestlah-browserstack/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<parent>
<groupId>qa.justtestlah</groupId>
<artifactId>justtestlah-parent</artifactId>
<version>1.9-RC1</version>
<version>1.9-RC2</version>
</parent>
<licenses>
<license>
Expand Down
2 changes: 1 addition & 1 deletion justtestlah-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<parent>
<groupId>qa.justtestlah</groupId>
<artifactId>justtestlah-parent</artifactId>
<version>1.9-RC1</version>
<version>1.9-RC2</version>
</parent>
<licenses>
<license>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.cucumber.junit;

import static io.cucumber.junit.FileNameCompatibleNames.uniqueSuffix;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;

import io.cucumber.core.eventbus.EventBus;
Expand All @@ -16,6 +18,8 @@
import io.cucumber.core.resource.ClassLoaders;
import io.cucumber.core.runtime.BackendServiceLoader;
import io.cucumber.core.runtime.BackendSupplier;
import io.cucumber.core.runtime.CucumberExecutionContext;
import io.cucumber.core.runtime.ExitStatus;
import io.cucumber.core.runtime.FeaturePathFeatureSupplier;
import io.cucumber.core.runtime.ObjectFactoryServiceLoader;
import io.cucumber.core.runtime.ObjectFactorySupplier;
Expand All @@ -24,14 +28,13 @@
import io.cucumber.core.runtime.ThreadLocalRunnerSupplier;
import io.cucumber.core.runtime.TimeServiceEventBus;
import io.cucumber.core.runtime.TypeRegistryConfigurerSupplier;
import io.cucumber.plugin.event.TestRunFinished;
import io.cucumber.plugin.event.TestRunStarted;
import io.cucumber.plugin.event.TestSourceRead;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.time.Clock;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Predicate;
import java.util.function.Supplier;
Expand Down Expand Up @@ -68,6 +71,7 @@ public class JustTestLahRunner extends ParentRunner<ParentRunner<?>> {
private EventBus bus = null;
private PropertiesHolder properties = new PropertiesHolder();
private boolean multiThreadingAssumed = false;
private CucumberExecutionContext context = null;

private static final String CLOUD_PROVIDER = "cloudprovider";
private static final String PLATFORM_KEY = "platform";
Expand Down Expand Up @@ -109,7 +113,8 @@ public JustTestLahRunner(Class<?> clazz) throws InitializationError, IOException
private void initCucumber(Class<?> clazz) throws InitializationError {
Assertions.assertNoCucumberAnnotatedMethods(clazz);

// Parse the options early to provide fast feedback about invalid options
// Parse the options early to provide fast feedback about invalid
// options
RuntimeOptions propertiesFileOptions =
new CucumberPropertiesParser().parse(CucumberProperties.fromPropertiesFile()).build();

Expand All @@ -127,16 +132,9 @@ private void initCucumber(Class<?> clazz) throws InitializationError {
RuntimeOptions runtimeOptions =
new CucumberPropertiesParser()
.parse(CucumberProperties.fromSystemProperties())
.addDefaultSummaryPrinterIfAbsent()
.enablePublishPlugin()
.build(environmentOptions);

if (!runtimeOptions.isStrict()) {
LOG.warn(
"By default Cucumber is running in --non-strict mode.\n"
+ "This default will change to --strict and --non-strict will be removed.\n"
+ "You can use --strict or @CucumberOptions(strict = true) to suppress this warning");
}

// Next parse the junit options
JUnitOptions junitPropertiesFileOptions =
new JUnitOptionsParser().parse(CucumberProperties.fromPropertiesFile()).build();
Expand All @@ -152,7 +150,6 @@ private void initCucumber(Class<?> clazz) throws InitializationError {
JUnitOptions junitOptions =
new JUnitOptionsParser()
.parse(CucumberProperties.fromSystemProperties())
.setStrict(runtimeOptions.isStrict())
.build(junitEnvironmentOptions);

this.bus = new TimeServiceEventBus(Clock.systemUTC(), UUID::randomUUID);
Expand All @@ -164,9 +161,11 @@ private void initCucumber(Class<?> clazz) throws InitializationError {
new FeaturePathFeatureSupplier(classLoader, runtimeOptions, parser);
this.features = featureSupplier.get();

// Create plugins after feature parsing to avoid the creation of empty files on
// lexer errors.
// Create plugins after feature parsing to avoid the creation of empty
// files on lexer errors.
this.plugins = new Plugins(new PluginFactory(), runtimeOptions);
ExitStatus exitStatus = new ExitStatus(runtimeOptions);
this.plugins.addPlugin(exitStatus);

ObjectFactoryServiceLoader objectFactoryServiceLoader =
new ObjectFactoryServiceLoader(runtimeOptions);
Expand All @@ -183,10 +182,19 @@ private void initCucumber(Class<?> clazz) throws InitializationError {
backendSupplier,
objectFactorySupplier,
typeRegistryConfigurerSupplier);
this.context = new CucumberExecutionContext(bus, exitStatus, runnerSupplier);
Predicate<Pickle> filters = new Filters(runtimeOptions);

Map<Optional<String>, List<Feature>> groupedByName =
features.stream().collect(groupingBy(Feature::getName));
this.children =
features.stream()
.map(feature -> FeatureRunner.create(feature, filters, runnerSupplier, junitOptions))
.map(
feature -> {
Integer uniqueSuffix = uniqueSuffix(groupedByName, feature, Feature::getName);
return FeatureRunner.create(
feature, uniqueSuffix, filters, runnerSupplier, junitOptions);
})
.filter(runner -> !runner.isEmpty())
.collect(toList());

Expand Down Expand Up @@ -225,6 +233,7 @@ public void setScheduler(RunnerScheduler scheduler) {
}

class RunCucumber extends Statement {

private final Statement runFeatures;

RunCucumber(Statement runFeatures) {
Expand All @@ -239,12 +248,14 @@ public void evaluate() throws Throwable {
plugins.setEventBusOnEventListenerPlugins(bus);
}

bus.send(new TestRunStarted(bus.getInstant()));
for (Feature feature : features) {
bus.send(new TestSourceRead(bus.getInstant(), feature.getUri(), feature.getSource()));
context.startTestRun();
features.forEach(context::beforeFeature);

try {
runFeatures.evaluate();
} finally {
context.finishTestRun();
}
runFeatures.evaluate();
bus.send(new TestRunFinished(bus.getInstant()));
}
}

Expand Down
22 changes: 17 additions & 5 deletions justtestlah-core/src/main/java/qa/justtestlah/base/BasePage.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -30,6 +31,7 @@
import qa.justtestlah.stubs.Applitools;
import qa.justtestlah.stubs.Galen;
import qa.justtestlah.stubs.Match;
import qa.justtestlah.stubs.OCR;
import qa.justtestlah.stubs.TemplateMatcher;
import qa.justtestlah.utils.ImageUtils;

Expand All @@ -52,6 +54,8 @@ public abstract class BasePage<T> extends Base {

@Autowired private Galen galen;

@Autowired private OCR ocr;

@Autowired private TestLogWriter logWriter;

protected LocatorMap getLocators() {
Expand Down Expand Up @@ -99,7 +103,11 @@ public boolean hasImage(String imageName) {
* @return true, if the image has been found on the current screen
*/
public boolean hasImage(String imageName, double threshold) {
return findImage(imageName, threshold).isFound();
return findImage(imageName, threshold).isDisplayed();
}

public WebElement findImage(String imageName) {
return findImage(imageName, 0.9);
}

/**
Expand All @@ -109,7 +117,7 @@ public boolean hasImage(String imageName, double threshold) {
* @param threshold matching threshold
* @return {@link Match}
*/
public Match findImage(String imageName, double threshold) {
public WebElement findImage(String imageName, double threshold) {
WebDriver driver = WebDriverRunner.getWebDriver();
if (driver instanceof TakesScreenshot) {
File screenshotFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
Expand All @@ -121,8 +129,12 @@ public Match findImage(String imageName, double threshold) {
}
((AppiumTemplateMatcher) templateMatcher).setDriver(WebDriverRunner.getWebDriver());
}
return templateMatcher.match(
screenshotFile.getAbsolutePath(), ImageUtils.getFullPath(imageName), threshold);
String path = ImageUtils.getFullPath(imageName);
return new ImageWebElement(
driver,
templateMatcher.match(screenshotFile.getAbsolutePath(), path, threshold).getRect(),
ocr,
path);
} else {
throw new UnsupportedOperationException(
"This operation is not supported for the current WebDriver: "
Expand Down Expand Up @@ -186,7 +198,7 @@ private T checkLayout() {
String specPath =
baseFolder
+ File.separator
+ configuration.getPlatform()
+ configuration.getPlatform().toString().toLowerCase()
+ File.separator
+ baseName
+ ".spec";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package qa.justtestlah.base;

import java.io.File;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Point;
import org.openqa.selenium.Rectangle;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import qa.justtestlah.stubs.OCR;

public class ImageWebElement implements WebElement {

public ImageWebElement(WebDriver driver, Rectangle rect, OCR ocr, String path) {
super();
this.driver = driver;
this.rect = rect;
this.ocr = ocr;
this.path = path;
}

protected WebDriver driver;
protected Rectangle rect;
protected OCR ocr;
protected String path;

@Override
public <X> X getScreenshotAs(OutputType<X> target) throws WebDriverException {
return (X) new File(path);
}

@Override
public void click() {
int x = rect.x + rect.width / 2;
int y = rect.y + rect.height / 2;
if (driver instanceof JavascriptExecutor) {
((JavascriptExecutor) driver)
.executeScript(
String.format("el = document.elementFromPoint(%d, %d); el.click();", x, y));
}
}

@Override
public void submit() {
throw new UnsupportedOperationException("operation not supported");
}

@Override
public void sendKeys(CharSequence... keysToSend) {
throw new UnsupportedOperationException("operation not supported");
}

@Override
public void clear() {
throw new UnsupportedOperationException("operation not supported");
}

@Override
public String getTagName() {
throw new UnsupportedOperationException("operation not supported");
}

@Override
public String getAttribute(String name) {
throw new UnsupportedOperationException("operation not supported");
}

@Override
public boolean isSelected() {
throw new UnsupportedOperationException("operation not supported");
}

@Override
public boolean isEnabled() {
throw new UnsupportedOperationException("operation not supported");
}

@Override
public String getText() {
return ocr.getText(this);
}

@Override
public <T extends WebElement> List<T> findElements(By by) {
throw new UnsupportedOperationException("operation not supported");
}

@Override
public <T extends WebElement> T findElement(By by) {
throw new UnsupportedOperationException("operation not supported");
}

@Override
public boolean isDisplayed() {
return rect != null;
}

@Override
public Point getLocation() {
return new Point(rect.x, rect.y);
}

@Override
public Dimension getSize() {
return new Dimension(rect.width, rect.height);
}

@Override
public Rectangle getRect() {
return rect;
}

@Override
public String getCssValue(String propertyName) {
throw new UnsupportedOperationException("operation not supported");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public static void setCucumberOptions(PropertiesHolder properties) {
setCucumberProperty(Constants.FILTER_TAGS_PROPERTY_NAME, buildTagsProperty(properties));
setCucumberProperty(Constants.GLUE_PROPERTY_NAME, buildGlueProperty(properties));
setCucumberProperty(Constants.PLUGIN_PROPERTY_NAME, buildPluginProperty(properties));
setCucumberProperty(Constants.PLUGIN_PUBLISH_ENABLED_PROPERTY_NAME, "true");
setCucumberProperty(Constants.EXECUTION_STRICT_PROPERTY_NAME, "true");
}

Expand All @@ -37,13 +38,6 @@ private static void setCucumberProperty(String key, String value) {

private static String buildPluginProperty(PropertiesHolder properties) {
StringBuilder pluginProperty = new StringBuilder(CucumberLoggingPlugin.class.getName());
pluginProperty.append(DELIMITER);
pluginProperty.append("html:report");
pluginProperty.append(DELIMITER);
pluginProperty.append("json:");
pluginProperty.append(
properties.getProperty(CUCUMBER_REPORT_DIRECTORY_KEY, DEFAULT_CUCUMBER_REPORT_DIRECTORY));
pluginProperty.append("/cucumber.json");
return pluginProperty.toString();
}

Expand Down
Loading

0 comments on commit 5690a31

Please sign in to comment.