package br.gov.frameworkdemoiselle.behave.regression.report.imagemagick;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.FilenameUtils;
import org.apache.maven.plugin.logging.Log;
import com.google.common.io.Files;
import br.gov.frameworkdemoiselle.behave.regression.report.ReportConfig;
import br.gov.frameworkdemoiselle.behave.regression.report.imagemagick.report.BrowserResultColumn;
import br.gov.frameworkdemoiselle.behave.regression.report.imagemagick.report.ComparisonStrategy;
import br.gov.frameworkdemoiselle.behave.regression.report.imagemagick.report.ReportBuilder;
import br.gov.frameworkdemoiselle.behave.regression.report.imagemagick.report.ReportType;
import br.gov.frameworkdemoiselle.behave.regression.report.imagemagick.report.ResultRow;
import br.gov.frameworkdemoiselle.behave.regression.report.imagemagick.util.CommandBuilder;
import br.gov.frameworkdemoiselle.behave.regression.report.imagemagick.util.Image;
import br.gov.frameworkdemoiselle.behave.regression.report.imagemagick.util.ImageUtil;
import br.gov.frameworkdemoiselle.behave.regression.report.imagemagick.util.StreamGobbler;
public class ImageMagickCompare {
private String diffScreenshotPath;
private String pathToImCompareBinary;
private String pathToImConvertBinary;
private String resultsFilePath;
private ReportBuilder reportBuilder;
private Log log;
private String prefixDiffPng = "pngdiff";
private String prefixDiffGif = "gifdiff";
private String prefixExpected = "expected";
private String prefixOriginal = "orig";
public ImageMagickCompare(ReportConfig config, Log log) {
// this.pathToImCompareBinary = "/usr/local/bin/compare";
// this.pathToImConvertBinary = "/usr/local/bin/convert";
this.pathToImCompareBinary = "compare";
this.pathToImConvertBinary = "convert";
this.log = log;
ReportType reportType = ReportType.HTML;
resultsFilePath = getResultsFilePath(config, reportType);
reportBuilder = ReportType.getReportBuilder(reportType, resultsFilePath);
}
private String getResultsFilePath(ReportConfig properties, ReportType reportType) {
String extension = ReportType.getFileExtension(reportType);
StringBuilder resultsFilePath = new StringBuilder();
resultsFilePath.append(new File("target/dbehave").getAbsolutePath());
resultsFilePath.append(File.separator + "index");
resultsFilePath.append(".");
resultsFilePath.append(extension);
log.info("O relatório será salvo no seguinte path: file://" + resultsFilePath.toString());
return resultsFilePath.toString();
}
public void compareAndCaptureResultsWithLists(List<String> types, List<List<File>> typesFilesList, String expectedType, List<File> expectedFilesList) {
try {
diffScreenshotPath = new File("target/dbehave").getAbsolutePath();
checkIfDiffFolderExists();
for (int i = 0; i < expectedFilesList.size(); i++) {
List<BrowserResultColumn> browsersResults = new ArrayList<BrowserResultColumn>();
// Arquivo original do navegador de referencia, sempre copia
// pois pode ter sido modificado
File expectedFileOriginal = expectedFilesList.get(i);
String pathExpectedFile = diffScreenshotPath + File.separator + prefixExpected + "_" + expectedType + "__" + expectedFilesList.get(i).getName();
// Pega a primeira tela do primeiro navegador
for (int j = 0; j < types.size(); j++) {
// Reinicia a imagem de referencia por causa dos
// redimensionamentos
File expectedFile = new File(pathExpectedFile);
Files.copy(expectedFileOriginal, expectedFile);
// Arquivo atual
File currentFile = typesFilesList.get(j).get(i);
String currentTypeName = types.get(j).replaceAll("^/", "");
Image expectedImage = new Image(expectedFilesList.get(i).getAbsolutePath());
Image currentImage = new Image(currentFile.getAbsolutePath());
// log.info("diffScreenshotPath: " + diffScreenshotPath);
// Arquivo original do navegador atual
String pathOrigFile = diffScreenshotPath + File.separator + prefixOriginal + "_" + currentTypeName + "__" + expectedFilesList.get(i).getName();
File newFileOriginal = new File(pathOrigFile);
Files.copy(currentFile, newFileOriginal);
// Trata o tamanho da imagem antes de rodar os comandos do
// Image Magick
try {
ImageUtil.imageConvert(currentFile.getAbsolutePath(), expectedFile.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
// Diff em PNG
String pathDiffFile = diffScreenshotPath + File.separator + prefixDiffPng + "_" + currentTypeName + "__" + expectedFilesList.get(i).getName();
CommandBuilder commandBuilder = buildCommand(currentFile, currentImage, expectedFile, expectedImage, pathDiffFile);
String commandOutput = executeCommandAndGetOutput(commandBuilder.getCommandAsArray());
// Diff em GIF
String pathDiffFileGif = diffScreenshotPath + File.separator + prefixDiffGif + "_" + currentTypeName + "__" + FilenameUtils.removeExtension(expectedFilesList.get(i).getName()) + ".gif";
CommandBuilder commandBuilderGif = buildCommandForGif(currentFile, currentImage, expectedFile, expectedImage, pathDiffFileGif);
executeCommandAndGetOutput(commandBuilderGif.getCommandAsArray());
// Linha do relatório
browsersResults.add(new BrowserResultColumn(types.get(j), pathOrigFile, pathDiffFile, pathDiffFileGif, expectedImage.getTotalPixels(), currentImage.getTotalPixels(), commandOutput, ComparisonStrategy.ONE_TO_ONE));
}
ResultRow resultRow = getResultRow(FilenameUtils.removeExtension(expectedFilesList.get(i).getName()), expectedType, pathExpectedFile, browsersResults);
reportBuilder.addResultRow(resultRow);
reportBuilder.build(diffScreenshotPath);
}
} catch (IOException e) {
log.error(e);
} catch (InterruptedException e) {
log.error(e);
}
}
private void checkIfDiffFolderExists() {
File diffFolder = new File(diffScreenshotPath);
try {
if (!diffFolder.isDirectory()) {
boolean makeDir = diffFolder.mkdir();
if (!makeDir) {
throw new RuntimeException("Failed to create diff images directory");
}
}
} catch (Exception e) {
log.error(e);
}
}
private ResultRow getResultRow(String nameStep, String expectedBrowser, String expectedFileName, List<BrowserResultColumn> browsers) throws IOException {
ResultRow resultRow = new ResultRow();
resultRow.setName(nameStep);
resultRow.setExpectedBrowser(expectedBrowser);
resultRow.setExpectedFileName(expectedFileName);
resultRow.setBrowsers(browsers);
return resultRow;
}
private CommandBuilder buildCommand(File currentFile, Image currentImage, File expectedFile, Image expectedImage, String pathDiffImageFile) {
CommandBuilder commandBuilder = new CommandBuilder();
commandBuilder.setPathToImageMagickCommandBinary(pathToImCompareBinary);
commandBuilder.setFirstImagePixels(expectedImage.getTotalPixels());
commandBuilder.setSecondImagePixels(expectedImage.getTotalPixels());
commandBuilder.setFilePaths(currentFile.getAbsolutePath(), expectedFile.getAbsolutePath(), pathDiffImageFile);
commandBuilder.build();
return commandBuilder;
}
private CommandBuilder buildCommandForGif(File currentFile, Image currentImage, File expectedFile, Image expectedImage, String pathDiffImageFile) {
CommandBuilder commandBuilder = new CommandBuilder();
commandBuilder.setPathToImageMagickCommandBinary(pathToImConvertBinary);
commandBuilder.setFilePaths(currentFile.getAbsolutePath(), expectedFile.getAbsolutePath(), pathDiffImageFile);
commandBuilder.buildForGif();
return commandBuilder;
}
private String executeCommandAndGetOutput(String[] command) throws IOException, InterruptedException {
Process process = Runtime.getRuntime().exec(command);
StreamGobbler errorGobbler = gobbleStream(process);
// Saídas do console
log.debug("Saída do comando (Image Magick): " + process.waitFor());
log.debug("Saída alternativa do comando (Image Magick): " + errorGobbler.getOutputLine());
return errorGobbler.getOutputLine();
}
private StreamGobbler gobbleStream(Process process) {
StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "Error Stream");
StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "Input Stream");
errorGobbler.start();
outputGobbler.start();
return errorGobbler;
}
}