Skip to content

Commit

Permalink
[plugin-mobile-app] Add full view shooting strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
uarlouski committed Jun 21, 2022
1 parent a48e057 commit 2de8b52
Show file tree
Hide file tree
Showing 49 changed files with 981 additions and 156 deletions.
21 changes: 21 additions & 0 deletions docs/modules/plugins/pages/plugin-visual.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,27 @@ When I <action> baseline with `scrollable-element-context` using screenshot conf
|51 |SIMPLE |
----

==== Strategies

[cols="1,3", options="header"]
|===

|Name
|Description

|`SIMPLE`
|Used to take a screenshot of current viewport. This strategy is used by default.

|`FULL`
|Used to take a screenshot of whole application view. The strategy starts shooting at the top position
of the application view and ends at the bottom position, once the shooting is done the initial top position
gets restored.

For iOS platform make sure to set the `screenshotQuality` property to `0` to ensure screenshot pixels
consistensy, please see https://github.com/appium/appium-xcuitest-driver[XCUI capabililties] for more details.

|===

== Steps

=== Run simple visual test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,13 @@

package org.vividus.selenium.screenshot;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;

import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.slf4j.Logger;
Expand Down Expand Up @@ -59,15 +52,6 @@ protected AbstractScreenshotTaker(IWebDriverProvider webDriverProvider,
this.screenshotDebugger = screenshotDebugger;
}

@Override
public BufferedImage takeViewportScreenshot() throws IOException
{
try (InputStream inputStream = new ByteArrayInputStream(takeScreenshotAsByteArray()))
{
return ImageIO.read(inputStream);
}
}

@Override
public Path takeScreenshot(Path screenshotFilePath) throws IOException
{
Expand Down Expand Up @@ -117,7 +101,7 @@ protected String generateScreenshotFileName(String screenshotName)

protected byte[] takeScreenshotAsByteArray()
{
return webDriverProvider.getUnwrapped(TakesScreenshot.class).getScreenshotAs(OutputType.BYTES);
return ScreenshotUtils.takeViewportScreenshotAsByteArray(getWebDriverProvider().get());
}

protected IWebDriverProvider getWebDriverProvider()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 the original author or authors.
* Copyright 2019-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,7 +16,6 @@

package org.vividus.selenium.screenshot;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
Expand All @@ -25,7 +24,5 @@ public interface ScreenshotTaker
{
Optional<Screenshot> takeScreenshot(String screenshotName);

BufferedImage takeViewportScreenshot() throws IOException;

Path takeScreenshot(Path screenshotFilePath) throws IOException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2019-2022 the original author or authors.
*
* 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
*
* https://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 org.vividus.selenium.screenshot;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.vividus.selenium.WebDriverUtils;

public final class ScreenshotUtils
{
private ScreenshotUtils()
{
}

public static BufferedImage takeViewportScreenshot(WebDriver webDriver) throws IOException
{
try (InputStream inputStream = new ByteArrayInputStream(takeViewportScreenshotAsByteArray(webDriver)))
{
return ImageIO.read(inputStream);
}
}

public static byte[] takeViewportScreenshotAsByteArray(WebDriver webDriver)
{
return WebDriverUtils.unwrap(webDriver, TakesScreenshot.class).getScreenshotAs(OutputType.BYTES);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@
import org.vividus.context.VariableContext;
import org.vividus.reporter.event.AttachmentPublishEvent;
import org.vividus.reporter.model.Attachment;
import org.vividus.selenium.IWebDriverProvider;
import org.vividus.selenium.screenshot.AshotScreenshotTaker;
import org.vividus.selenium.screenshot.ScreenshotTaker;
import org.vividus.selenium.screenshot.ScreenshotUtils;
import org.vividus.softassert.ISoftAssert;
import org.vividus.ui.action.BarcodeActions;
import org.vividus.ui.context.IUiContext;
Expand All @@ -47,20 +48,20 @@ public class BarcodeSteps
"There is no barcode on the selected context, page or screen";

private final IUiContext uiContext;
private final ScreenshotTaker screenshotTaker;
private final IWebDriverProvider webDriverProvider;
private final AshotScreenshotTaker<ScreenshotParameters> ashotScreenshotTaker;
private final BarcodeActions barcodeActions;
private final VariableContext variableContext;
private final ISoftAssert softAssert;
private final EventBus eventBus;

@SuppressWarnings({"rawtypes", "unchecked"})
public BarcodeSteps(IUiContext uiContext, ScreenshotTaker screenshotTaker,
public BarcodeSteps(IUiContext uiContext, IWebDriverProvider webDriverProvider,
AshotScreenshotTaker ashotScreenshotTaker, BarcodeActions barcodeActions, VariableContext variableContext,
ISoftAssert softAssert, EventBus eventBus)
{
this.uiContext = uiContext;
this.screenshotTaker = screenshotTaker;
this.webDriverProvider = webDriverProvider;
this.ashotScreenshotTaker = ashotScreenshotTaker;
this.barcodeActions = barcodeActions;
this.variableContext = variableContext;
Expand Down Expand Up @@ -90,7 +91,7 @@ public BarcodeSteps(IUiContext uiContext, ScreenshotTaker screenshotTaker,
@When("I scan barcode from screen and save result to $scopes variable `$variableName`")
public void scanBarcode(Set<VariableScope> scopes, String variableName) throws IOException
{
BufferedImage viewportScreenshot = screenshotTaker.takeViewportScreenshot();
BufferedImage viewportScreenshot = ScreenshotUtils.takeViewportScreenshot(webDriverProvider.get());

scanScreenshot(viewportScreenshot, scopes, variableName, NOT_FOUND_MESSAGE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,31 @@
package org.vividus.ui.util;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public final class ImageUtils
{
private static final String PNG_FORMAT_NAME = "png";

private ImageUtils()
{
}

public static void writeAsPng(BufferedImage toWrite, File location) throws IOException
public static void writeAsPng(BufferedImage image, File location) throws IOException
{
ImageIO.write(image, PNG_FORMAT_NAME, location);
}

public static byte[] encodeAsPng(BufferedImage image) throws IOException
{
ImageIO.write(toWrite, "png", location);
try (ByteArrayOutputStream output = new ByteArrayOutputStream())
{
ImageIO.write(image, PNG_FORMAT_NAME, output);
return output.toByteArray();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,16 @@
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
Expand All @@ -48,15 +47,14 @@
import org.junit.jupiter.api.io.TempDir;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.vividus.selenium.IWebDriverProvider;
import org.vividus.ui.screenshot.ScreenshotParameters;
import org.vividus.util.ResourceUtils;

import ru.yandex.qatools.ashot.AShot;

Expand All @@ -82,25 +80,6 @@ void afterEach()
verifyNoMoreInteractions(webDriverProvider, takesScreenshot);
}

private void mockScreenshotTaking()
{
byte[] bytes = ResourceUtils.loadResourceAsByteArray(getClass(), IMAGE_PNG);

when(webDriverProvider.getUnwrapped(TakesScreenshot.class)).thenReturn(takesScreenshot);
when(takesScreenshot.getScreenshotAs(OutputType.BYTES)).thenReturn(bytes);
}

@Test
void shouldTakeViewportScreenshot() throws IOException
{
mockScreenshotTaking();

BufferedImage image = testScreenshotTaker.takeViewportScreenshot();

assertEquals(400, image.getWidth());
assertEquals(600, image.getHeight());
}

@Test
void shouldGenerateScreenshotFileName()
{
Expand All @@ -112,20 +91,38 @@ void shouldGenerateScreenshotFileName()
@Test
void shouldNotPublishEmptyScreenshotData(@TempDir Path path) throws IOException
{
testScreenshotTaker.screenshot = new byte[0];
assertNull(testScreenshotTaker.takeScreenshot(path.resolve(IMAGE_PNG)));
assertThat(testLogger.getLoggingEvents(), empty());
try (MockedStatic<ScreenshotUtils> utils = mockStatic(ScreenshotUtils.class))
{
testScreenshotTaker.screenshot = new byte[0];

WebDriver webDriver = mock(WebDriver.class);
when(webDriverProvider.get()).thenReturn(webDriver);
utils.when(() -> ScreenshotUtils.takeViewportScreenshotAsByteArray(webDriver))
.thenReturn(testScreenshotTaker.screenshot);

assertNull(testScreenshotTaker.takeScreenshot(path.resolve(IMAGE_PNG)));
assertThat(testLogger.getLoggingEvents(), empty());
}
}

@Test
void shouldPublishScreenshot(@TempDir Path path) throws IOException
{
testScreenshotTaker.screenshot = new byte[1];
Path screenshotPath = testScreenshotTaker.takeScreenshot(path.resolve(IMAGE_PNG));
assertTrue(Files.exists(screenshotPath));
assertArrayEquals(testScreenshotTaker.screenshot, Files.readAllBytes(screenshotPath));
assertThat(testLogger.getLoggingEvents(), equalTo(List.of(
info("Screenshot was taken: {}", screenshotPath.toAbsolutePath()))));
try (MockedStatic<ScreenshotUtils> utils = mockStatic(ScreenshotUtils.class))
{
testScreenshotTaker.screenshot = new byte[1];

WebDriver webDriver = mock(WebDriver.class);
when(webDriverProvider.get()).thenReturn(webDriver);
utils.when(() -> ScreenshotUtils.takeViewportScreenshotAsByteArray(webDriver))
.thenReturn(testScreenshotTaker.screenshot);

Path screenshotPath = testScreenshotTaker.takeScreenshot(path.resolve(IMAGE_PNG));
assertTrue(Files.exists(screenshotPath));
assertArrayEquals(testScreenshotTaker.screenshot, Files.readAllBytes(screenshotPath));
assertThat(testLogger.getLoggingEvents(), equalTo(List.of(
info("Screenshot was taken: {}", screenshotPath.toAbsolutePath()))));
}
}

@Test
Expand Down Expand Up @@ -178,11 +175,5 @@ public Optional<Screenshot> takeScreenshot(String screenshotName)
{
throw new UnsupportedOperationException();
}

@Override
protected byte[] takeScreenshotAsByteArray()
{
return screenshot == null ? super.takeScreenshotAsByteArray() : screenshot;
}
}
}
Loading

0 comments on commit 2de8b52

Please sign in to comment.