/*******************************************************************************
* Copyright 2017 Ivan Shubin http://galenframework.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.galenframework.tests.validation;
import com.galenframework.components.validation.MockedPage;
import com.galenframework.page.PageElement;
import com.galenframework.page.Rect;
import com.galenframework.rainbow4j.filters.BlurFilter;
import com.galenframework.rainbow4j.filters.ImageFilter;
import com.galenframework.specs.SpecImage;
import com.galenframework.specs.page.PageSpec;
import com.galenframework.validation.PageValidation;
import com.galenframework.validation.ValidationError;
import com.galenframework.validation.ValidationObject;
import com.galenframework.validation.ValidationResult;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import static java.util.Arrays.asList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
public class ImageValidationTest extends ValidationTestBase {
private static final boolean PIXEL_UNIT = true;
private static final boolean PERCENTAGE_UNIT = false;
private BufferedImage imageComparisonTestScreenshot = loadTestImage("/imgs/page-screenshot.png");
private BufferedImage testImage = loadTestImage("/color-scheme-image-1.png");
@DataProvider
@Override
public Object[][] provideGoodSamples() {
return new Object[][] {
{specImage(asList("/imgs/button-sample-correct.png"), 1, PIXEL_UNIT, 0, 5), page(new HashMap<String, PageElement>(){{
put("object", element(100, 90, 100, 40));
}}, imageComparisonTestScreenshot)},
{specImage(asList("/imgs/page-sample-correct.png"), 2, PIXEL_UNIT, 0, 5, new Rect(40, 40, 100, 40)), page(new HashMap<String, PageElement>() {{
put("object", element(100, 90, 100, 40));
}}, imageComparisonTestScreenshot)},
{specImage(asList("/imgs/button-sample-incorrect.png", "/imgs/button-sample-correct.png"), 1, PIXEL_UNIT, 0, 5), page(new HashMap<String, PageElement>(){{
put("object", element(100, 90, 100, 40));
}}, imageComparisonTestScreenshot)},
{specImage(asList("/imgs/button-sample-*.png"), 1, PIXEL_UNIT, 0, 5), page(new HashMap<String, PageElement>(){{
put("object", element(100, 90, 100, 40));
}}, imageComparisonTestScreenshot)},
};
}
@DataProvider
@Override
public Object[][] provideBadSamples() {
return new Object[][] {
{validationResult(NO_AREA, messages("\"object\" is absent on page")),
specImage(asList("/imgs/button-sample-incorrect.png"), 2.0, true, 0, 10), page(new HashMap<String, PageElement>(){{
put("object", absentElement(10, 10, 400, 300));
}}, testImage)},
{validationResult(NO_AREA, messages("\"object\" is not visible on page")),
specImage(asList("/imgs/button-sample-incorrect.png"), 2.0, true, 0, 10), page(new HashMap<String, PageElement>(){{
put("object", invisibleElement(10, 10, 400, 300));
}}, testImage)},
{new ValidationResult(NO_SPEC, areas(new ValidationObject(new Rect(100, 90, 100, 40), "object")),
new ValidationError(messages("Element does not look like \"/imgs/button-sample-incorrect.png\". " +
"There are 3820 mismatching pixels but max allowed is 600"))),
specImage(asList("/imgs/button-sample-incorrect.png"), 600, PIXEL_UNIT, 0, 10), page(new HashMap<String, PageElement>() {{
put("object", element(100, 90, 100, 40));
}}, imageComparisonTestScreenshot)},
{new ValidationResult(NO_SPEC, areas(new ValidationObject(new Rect(100, 90, 100, 40), "object")),
new ValidationError(messages("Element does not look like \"/imgs/button-sample-incorrect.png\". " +
"There are 95.5% mismatching pixels but max allowed is 2%"))),
specImage(asList("/imgs/button-sample-incorrect.png"), 2.0, PERCENTAGE_UNIT, 0, 10), page(new HashMap<String, PageElement>() {{
put("object", element(100, 90, 100, 40));
}}, imageComparisonTestScreenshot)},
{new ValidationResult(NO_SPEC, areas(new ValidationObject(new Rect(100, 90, 100, 40), "object")),
new ValidationError(messages("Couldn't load image: /imgs/undefined-image.png"))),
specImage(asList("/imgs/undefined-image.png"), 1.452, PERCENTAGE_UNIT, 0, 10), page(new HashMap<String, PageElement>() {{
put("object", element(100, 90, 100, 40));
}}, imageComparisonTestScreenshot)}
};
}
@Test
public void imageSpec_shouldAlsoGenerate_imageComparisonMap() {
MockedPage page = page(new HashMap<String, PageElement>() {{
put("object", element(100, 90, 100, 40));
}}, imageComparisonTestScreenshot);
PageSpec pageSpec = createMockedPageSpec(page);
PageValidation validation = new PageValidation(null, page, pageSpec, null, null);
ValidationError error = validation.check("object", specImage(asList("/imgs/button-sample-incorrect.png"), 0, PIXEL_UNIT, 0, 10)).getError();
assertThat("Comparison map should not be null", error.getImageComparison().getComparisonMap(), is(notNullValue()));
}
private SpecImage specImage(List<String> imagePaths, double errorValue, boolean isPixelUnit, int pixelSmooth, int tolerance) {
return specImage(imagePaths, errorValue, isPixelUnit, pixelSmooth, tolerance, null);
}
private SpecImage specImage(List<String> imagePaths, double errorValue, boolean isPixelUnit, int blur, int tolerance, Rect selectedArea) {
SpecImage spec = new SpecImage();
if (isPixelUnit) {
spec.setErrorRate(new SpecImage.ErrorRate(errorValue, SpecImage.ErrorRateType.PIXELS));
}
else {
spec.setErrorRate(new SpecImage.ErrorRate(errorValue, SpecImage.ErrorRateType.PERCENT));
}
spec.setImagePaths(imagePaths);
List<ImageFilter> filters = new LinkedList<>();
spec.setOriginalFilters(filters);
spec.setSampleFilters(filters);
if (blur > 0) {
filters.add(new BlurFilter(blur));
}
spec.setTolerance(tolerance);
spec.setSelectedArea(selectedArea);
return spec;
}
}