How to attach screenshot to steps using AbstractTestNGCucumberTests? - cucumber

I want to attach screenshot to steps that is generated cucumber html report. My project use AbstractTestNGCucumberTests.
This is my takeScreenshot method:
public static void takeScreenshot(io.cucumber.core.api.Scenario scenario,
WebDriver driver, File screenShotFile) {
final byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
scenario.embed(screenshot, "image/png");
try {
OutputStream os = new FileOutputStream(screenShotFile);
os.write(screenshot);
Log.debug("Successfully save screenshot");
os.close();
} catch (Exception ex) {
Log.error("Exception : " + ex);
}
}
I try to get Scenario by declaring anotation io.cucumber.java.Before
But Scenario is null
Please help me how to get io.cucumber.core.api.Scenario or another way to attach screenshot in steps for reporting

I fixed my problem. Cucumber hook #Before is just run in location that is defined in #CucumberOptions(glue=my-path). My Class TestSuiteMaster is in another path, so Scenario is null.
I created a class CucumberHook in directory stepDefinition and take screen shot method in hook #After, everything work great.
This is my CucumberHook class:
public class CucumberHook extends WebTestSuiteMaster {
#After
public void take_screenshot_after_finished_scenario(Scenario scenario) {
String imageFileName = "Screen shot-" + scenario.getName() + "-"
+ new SimpleDateFormat("MM-dd-yyyy_HH-mm").format(new Date()) + ".png";
File imageFile = new File(System.getProperty("user.dir") + "//screenshots//" + imageFileName);
SeleniumWebHelper.takeScreenshot(scenario, driver, imageFile);
}
}

Related

org.testng.TestNGException: Method tearDown requires 1 parameters but 0 were supplied in the #Configuration annotation

I am not able to understand what is required as parameter, can anyone help me with this.
I have written below code:-
#Test(groups = "cucumber", description = "Runs Cucumber Feature", dataProvider = "features")
public void feature(CucumberFeatureWrapper cucumberFeature) throws Exception {
testNGCucumberRunner.runCucumber(cucumberFeature.getCucumberFeature());
}
#AfterMethod(alwaysRun = true)
public void tearDown(Scenario scenario) {
scenario.write("Finished Scenario");
if (scenario.isFailed()) {
String screenshotName = scenario.getName().replaceAll(" ", "_");
try {
File sourcePath =((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
File destinationPath = new File(System.getProperty("user.dir") + "/Screenshots/" + screenshotName + ".png");
Files.copy(sourcePath, destinationPath);
Reporter.addScreenCaptureFromPath(destinationPath.toString());
} catch (IOException e) {
}
driver.close();
}
}
And I am getting below error:-
FAILED CONFIGURATION: #AfterMethod tearDown
org.testng.TestNGException: Method tearDown requires 1 parameters but
0 were supplied in the #Configuration annotation.
You cannot pass a Cucumber Scenario object to a TestNg configuration method. The AfterMethod will be called by TestNg and will not be able to inject the Scenario object. For a list of objects that are injected automatically refer to this - http://testng.org/doc/documentation-main.html#native-dependency-injection
Either use the After annotation of Cucumber and pass the Scenario object.
#cucumber.api.java.After
public void tearDown(Scenario scenario)
Or use the AfterMethod of TestNg and pass the ITestResult object.
#org.testng.annotations.AfterMethod
public void tearDown(ITestResult result)

Writing my own image importer, pictures are not recognized as pictures after import

i am writing my own image import for my product catalog. I want to read the images from the local filesystem and store them in the configured assets folder. The import is very simple for now. Its one controller in the admin project and i trigger it by calling an url.
It is creating the files along with the folder structure and the files seem to have the same filesize, but somehow they get messed up along the way and they are not readable as images anymore (picture viewers wont open them). Any ideas why its being messed up ?
here the code:
#Controller("blImageImportController")
#RequestMapping("/imageimport")
public class ImageImportController extends AdminAbstractController {
#Value("${image.import.folder.location}")
private String importFolderLocation;
#Resource(name = "blStaticAssetService")
protected StaticAssetService staticAssetService;
#Resource(name = "blStaticAssetStorageService")
protected StaticAssetStorageService staticAssetStorageService;
#RequestMapping(method = {RequestMethod.GET})
public String chooseMediaForMapKey(HttpServletRequest request,
HttpServletResponse response,
Model model
) throws Exception {
File imageImportFolder = new File(importFolderLocation);
if (imageImportFolder.isDirectory()) {
Arrays.stream(imageImportFolder.listFiles()).forEach(directory ->
{
if (directory.isDirectory()) {
Arrays.stream(directory.listFiles()).forEach(this::processFile);
}
});
}
return "";
}
private void processFile(File file) {
FileInputStream fis = null;
try {
HashMap properties = new HashMap();
properties.put("entityType", "product");
properties.put("entityId", file.getParentFile().getName());
fis = new FileInputStream(file);
StaticAsset staticAsset = this.staticAssetService.createStaticAsset(fis, file.getName(), file.length(), properties);
this.staticAssetStorageService.createStaticAssetStorage(fis, staticAsset);
fis.close();
} catch (Exception e) {
} finally {
try {
if (fis != null)
fis.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
There is a check in the StaticAssetService to try to detect this as an image (see https://github.com/BroadleafCommerce/BroadleafCommerce/blob/b55848f/admin/broadleaf-contentmanagement-module/src/main/java/org/broadleafcommerce/cms/file/service/StaticAssetServiceImpl.java#L217-L220). If it detected this correctly, you should get back an ImageStaticAssetImpl in the result to that call.
The flipside of this is the controller that actually reads the file (the StaticAssetViewController that renders a StaticAssetView). One of the things that the StaticAssetView does is set a response header for mimeType which the browser uses to render. This is set by this piece in the StaticAssetStorageService: https://github.com/BroadleafCommerce/BroadleafCommerce/blob/b55848f837f26022a620f0c2c143eed7902ba3f1/admin/broadleaf-contentmanagement-module/src/main/java/org/broadleafcommerce/cms/file/service/StaticAssetStorageServiceImpl.java#L213. I suspect that is the root of your problem.
Also just a note, sending those properties is not necessary when you are uploading the file yourself. That is mainly used in the admin when you are uploading an image for a specific entity (like a product or a category).

TextArea is not updating while zip extraction

I am working on a JavaFx application, there i have a script that extract a zip followed by some other operation like updating files etc.
I want to have a textArea that displays whats going on in background, like "Zip extracting...", "Updating xyz file" etc.
Till now i have tried following way:
MyTask<String> task;
task = new MyTask<String>() {
#Override
protected String call() throws Exception {
File path = new File(exportTo.getAbsolutePath());
updateMessage("Extracting modular app to target directory...");
patcher.unZip(appPath.getAbsolutePath(), path.getAbsolutePath());
if (path.exists()) {
AppInfo info = getAppInfo();
patcher.patchAndroid(info, resourceZip, new File(path.getAbsolutePath() + "/" + appPath.getName().substring(0, appPath.getName().lastIndexOf("."))), this);
showOkAlert("Build completed!");
} else {
showOkAlert("Modular app folder not found");
}
return "";
}
#Override
protected void updateProgress(double workDone, double max) {
patcher.reportLogs(message);
}
private String message;
#Override
public void updateMessage(final String message) {
Platform.runLater(() -> patcher.reportLogs(message));
this.message = message;
//updateProgress(0, 0);
}
};
task.run();
MyTask class
abstract class MyTask<T> extends Task<T> {
abstract public void updateMessage(String message);
}
I have tried using updateProgress method, Platform.runLater() but nothing is working.
All the message i printed in textArea are printed after all operation is done.
Please help.
As javadoc for Task states you need to manually create a Thread to execute your Task:
Thread th = new Thread(task);
th.start();
Currently your task is being run on Application UI thread and blocks UI updates.

Downloads with JavaFX WebView

my web application offers a download. Javascript creats at the click the url (it depends on the user input) and the browser should open it, so that the page isn't reloaded.
For that, I think I have to alternatives:
// Alt1:
window.open(pathToFile);
// Alt2:
var downloadFrame = document.getElementById('downloads');
if (downloadFrame === null) {
downloadFrame = document.createElement('iframe');
downloadFrame.id = 'downloads';
downloadFrame.style.display = 'none';
document.body.appendChild(downloadFrame);
}
downloadFrame.src = pathToFile;
Both works under Firefox. Problem with open new window method: If the creation of the file at the server needs more time, the new empty tab will be closed late.
Problem with iframe: If there is an error at the server, no feedback is given.
I think at firefox the iframe is the better solution. But the web application must run with an JavaFX WebView, too. JavaFX haven't a download feature, I have to write it. One possible way is to listen on the location property:
final WebView webView = new WebView();
webView.getEngine().locationProperty().addListener(new ChangeListener<String>() {
#Override public void changed(ObservableValue<? extends String> observableValue, String oldLoc, String newLoc) {
if (newLoc.cotains("/download")) {
FileChooser chooser = new FileChooser();
chooser.setTitle("Save " + newLoc);
File saveFile = chooser.showSaveDialog(webView.getEngine().getScene().getWindow());
if (saveFile != null) {
BufferedInputStream is = null;
BufferedOutputStream os = null;
try {
is = new BufferedInputStream(new URL(newLoc).openStream());
os = new BufferedOutputStream(new FileOutputStream(saveFile));
while ((readBytes = is.read()) != -1) {
os.write(b);
}
} finally {
try { if (is != null) is.close(); } catch (IOException e) {}
try { if (os != null) os.close(); } catch (IOException e) {}
}
}
}
}
}
There are some problems:
The download start depends on a part of the url, because JafaFX supports no access to the http headers (that is bearable)
If the user starts the download with the same url two times, only the first download works (the change event only fires, if the url is new). I can crate unique urls (with #1, #2 and so on at the end). But this is ugly.
Only the "window.open(pathToFile);" method works. Loading an iframe don't fire the change location event of the website. That is expectable but I haven't found the right Listener.
Can someone help me to solve 2. or 3.?
Thank you!
PS: Sorry for my bad english.
edit:
For 2. I found a way. I don't know if it is a good one, if it is performant, if the new webview is deleted or is in the cache after download, ....
And the user don't get an feedback, when some a problem is raised:
webView.getEngine().setCreatePopupHandler(new Callback<PopupFeatures, WebEngine>() {
#Override public WebEngine call(PopupFeatures config) {
final WebView downloader = new WebView();
downloader.getEngine().locationProperty().addListener(/* The Listener from above */);
return downloader.getEngine();
}
}
I think you may just need to use copyURLtoFile to get the file...call that when the location changes or just call that using a registered java class. Something like this:
org.apache.commons.io.FileUtils.copyURLToFile(new URL(newLoc), new File(System.getProperty("user.home")+filename));
Using copyURLToFile the current page doesn't have to serve the file. I think registering the class is probably the easiest way to go... something like this:
PHP Code:
Download $filename
Java (in-line class in your javafx class/window... in this case my javafx window is inside of a jframe):
public class JavaApp {
JFrame cloudFrameREF;
JavaApp(JFrame cloudFrameREF)
{
this.cloudFrameREF = cloudFrameREF;
}
public void getfile(String filename) {
String newLoc = "http://your_web_site.com/send_file.php?filename=" + filename;
org.apache.commons.io.FileUtils.copyURLToFile(new URL(newLoc), new File(System.getProperty("user.home")+filename));
}
}
This part would go in the main javafx class:
Platform.runLater(new Runnable() {
#Override
public void run() {
browser2 = new WebView();
webEngine = browser2.getEngine();
appREF = new JavaApp(cloudFrame);
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
#Override public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject win
= (JSObject) webEngine.executeScript("window");
// this next line registers the JavaApp class with the page... you can then call it from javascript using "app.method_name".
win.setMember("app", appREF);
}
}
});
You may not need the frame reference... I was hacking some of my own code to test this out and the ref was useful for other things...

javafx-2 applet doesn't update gui when called from javascript

I'm trying to invoke a method from javascript object which in turn calls a the following java method :
public void loadPicture(final String absolutePath) {
System.out.println("loadPicture " + absolutePath);
Image dbimage;
dbimage = new Image(absolutePath, 100.0d, 100.0d, false, false);
final ImageView dbImageView = new ImageView();
dbImageView.setImage(dbimage);
Platform.runLater(new Runnable() {
#Override
public void run() {
try {
System.out.println("hbox children : "+hbox.getChildren().size());
hbox.getChildren().add(dbImageView);
System.out.println("hbox children : "+hbox.getChildren().size());
//test
//logger.debug(" aggiunto "+absolutePath);
DropPictures.getPicturesNames().add(absolutePath);
} catch (Exception e) {
System.out.println("eccezione :" + e.getLocalizedMessage());
}
}
});
}
In javascript the method invocation is :
var a = document.getElementById(myDivId);
a.loadPicture();
I've traced the execution and the above method doesn't throw any exception,but it is run cause i see the output in java console, but the applet doesn't show the picture.
I've used Platform.runLater to update the GUI in the javafx thread, still no update is performed.

Resources