Skip to content

Commit

Permalink
Video in extent report
Browse files Browse the repository at this point in the history
  • Loading branch information
giulong committed Nov 18, 2023
1 parent 994a3f3 commit 22b1300
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@
import com.aventstack.extentreports.Status;
import com.aventstack.extentreports.markuputils.ExtentColor;
import io.github.giulong.spectrum.SpectrumSessionListener;
import io.github.giulong.spectrum.pojos.Configuration;
import io.github.giulong.spectrum.types.TestData;
import io.github.giulong.spectrum.utils.video.Video;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolutionException;
import org.junit.jupiter.api.extension.support.TypeBasedParameterResolver;

import java.nio.file.Path;

import static com.aventstack.extentreports.Status.INFO;
import static com.aventstack.extentreports.markuputils.ExtentColor.*;
import static com.aventstack.extentreports.markuputils.MarkupHelper.createLabel;
import static io.github.giulong.spectrum.extensions.resolvers.ConfigurationResolver.CONFIGURATION;
import static io.github.giulong.spectrum.extensions.resolvers.TestDataResolver.TEST_DATA;
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;

@Slf4j
Expand Down Expand Up @@ -43,8 +50,21 @@ public static ExtentColor getColorOf(final Status status) {
@Override
public ExtentTest resolveParameter(final ParameterContext arg0, final ExtensionContext context) throws ParameterResolutionException {
log.debug("Resolving {}", EXTENT_TEST);
final ExtentTest extentTest = createExtentTestFrom(context).info(createLabel("START TEST", getColorOf(INFO)));
context.getStore(GLOBAL).put(EXTENT_TEST, extentTest);
final ExtensionContext.Store store = context.getStore(GLOBAL);
final ExtentTest extentTest = createExtentTestFrom(context);
final Video video = store.get(CONFIGURATION, Configuration.class).getVideo();
final Video.ExtentTest videoExtentTest = video.getExtentTest();

if (!video.isDisabled() && videoExtentTest.isAttach()) {
final int width = videoExtentTest.getWidth();
final int height = videoExtentTest.getHeight();
final Path src = store.get(TEST_DATA, TestData.class).getVideoPath();

extentTest.info(String.format("<video controls width=\"%d\" height=\"%d\" src=\"%s\" type=\"video/mp4\"/>", width, height, src));
}

extentTest.info(createLabel("START TEST", getColorOf(INFO)));
store.put(EXTENT_TEST, extentTest);

return extentTest;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.nio.file.Path;

import static io.github.giulong.spectrum.extensions.resolvers.ConfigurationResolver.CONFIGURATION;
import static java.util.UUID.randomUUID;
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;

@Slf4j
Expand All @@ -28,11 +29,13 @@ public TestData resolveParameter(final ParameterContext arg0, final ExtensionCon
final String className = context.getRequiredTestClass().getSimpleName();
final String methodName = context.getRequiredTestMethod().getName();
final Path screenshotFolderPath = getScreenshotFolderPathForCurrentTest(reportFolder, className, methodName);
final Path videoPath = getVideoPathForCurrentTest(reportFolder, className, methodName);
final TestData testData = TestData
.builder()
.className(className)
.methodName(methodName)
.screenshotFolderPath(screenshotFolderPath)
.videoPath(videoPath)
.build();

context.getStore(GLOBAL).put(TEST_DATA, testData);
Expand All @@ -45,4 +48,11 @@ public Path getScreenshotFolderPathForCurrentTest(final String reportsFolder, fi
Files.createDirectories(path);
return path;
}

@SneakyThrows
public Path getVideoPathForCurrentTest(final String reportsFolder, final String className, final String methodName) {
final Path path = Path.of(reportsFolder, "videos", className, methodName).toAbsolutePath();
Files.createDirectories(path);
return path.resolve(String.format("%s.mp4", randomUUID()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import io.github.giulong.spectrum.types.TestData;
import io.github.giulong.spectrum.utils.video.Video;
import io.github.giulong.spectrum.utils.video.VideoEncoder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
Expand All @@ -13,15 +12,13 @@
import org.openqa.selenium.WebDriver;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.BlockingQueue;

import static io.github.giulong.spectrum.extensions.resolvers.ConfigurationResolver.CONFIGURATION;
import static io.github.giulong.spectrum.extensions.resolvers.ScreenshotQueueResolver.SCREENSHOT_QUEUE;
import static io.github.giulong.spectrum.extensions.resolvers.TestDataResolver.TEST_DATA;
import static io.github.giulong.spectrum.extensions.resolvers.WebDriverResolver.WEB_DRIVER;
import static java.util.UUID.randomUUID;
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;

@Slf4j
Expand All @@ -43,7 +40,7 @@ public VideoEncoder resolveParameter(final ParameterContext arg0, final Extensio
final TestData testData = store.get(TEST_DATA, TestData.class);
final String className = testData.getClassName();
final String methodName = testData.getMethodName();
final Path videoPath = getVideoPathForCurrentTest(configuration.getExtent().getReportFolder(), className, methodName);
final Path videoPath = testData.getVideoPath();
final WebDriver webDriver = store.get(WEB_DRIVER, WebDriver.class);
@SuppressWarnings("unchecked")
final BlockingQueue<File> screenshotsQueue = (BlockingQueue<File>) store.get(SCREENSHOT_QUEUE, BlockingQueue.class);
Expand All @@ -54,11 +51,4 @@ public VideoEncoder resolveParameter(final ParameterContext arg0, final Extensio

return videoEncoder;
}

@SneakyThrows
public Path getVideoPathForCurrentTest(final String reportsFolder, final String className, final String methodName) {
final Path path = Path.of(reportsFolder, "videos", className, methodName).toAbsolutePath();
Files.createDirectories(path);
return path.resolve(String.format("%s.mp4", randomUUID()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ public class TestData {
private String className;
private String methodName;
private Path screenshotFolderPath;
private Path videoPath;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class Video {
private List<Frame> frames;
private int width;
private int height;
private ExtentTest extentTest;

public boolean isDisabled() {
return frames.isEmpty();
Expand All @@ -23,4 +24,11 @@ public boolean shouldRecord(final String frameName) {
.map(Frame::getValue)
.anyMatch(frameName::startsWith);
}

@Getter
public static class ExtentTest {
private boolean attach;
private int width;
private int height;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ public class VideoEncoder extends Thread {
private final BlockingQueue<File> blockingQueue;
private final String className;
private final String methodName;
private final File file;
private final AWTSequenceEncoder encoder;
private final Video video;
private final Dimension dimension;
Expand All @@ -34,7 +33,6 @@ public VideoEncoder(final BlockingQueue<File> blockingQueue, final String classN
this.blockingQueue = blockingQueue;
this.className = className;
this.methodName = methodName;
this.file = file;
this.video = video;
this.dimension = chooseDimensionFor(webDriver);
this.encoder = AWTSequenceEncoder.createSequenceEncoder(file, 1);
Expand Down
6 changes: 6 additions & 0 deletions spectrum/src/main/resources/yaml/configuration.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ testBook: null
# Execution video recording
video:
frames: [ ] # by default, nothing is recorded
width: 0 # width of the video. A value of 0 means the actual browser size will be used
height: 0 # height of the video. A value of 0 means the actual browser size will be used
extentTest:
attach: true # by default, the video (if recorded) is attached to the extent report
width: 320 # width of the video in the extent report
height: 240 # height of the video in the extent report

# Extent Report configuration
extent:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
import com.aventstack.extentreports.markuputils.ExtentColor;
import com.aventstack.extentreports.markuputils.Markup;
import io.github.giulong.spectrum.SpectrumSessionListener;
import io.github.giulong.spectrum.pojos.Configuration;
import io.github.giulong.spectrum.types.TestData;
import io.github.giulong.spectrum.utils.video.Video;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
Expand All @@ -22,16 +25,18 @@
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;

import java.nio.file.Path;
import java.util.Optional;
import java.util.stream.Stream;

import static com.aventstack.extentreports.Status.*;
import static com.aventstack.extentreports.markuputils.ExtentColor.*;
import static com.aventstack.extentreports.markuputils.MarkupHelper.createLabel;
import static io.github.giulong.spectrum.extensions.resolvers.ConfigurationResolver.CONFIGURATION;
import static io.github.giulong.spectrum.extensions.resolvers.TestDataResolver.TEST_DATA;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
Expand All @@ -58,6 +63,21 @@ class ExtentTestResolverTest {
@Mock
private ExtentTest extentTest;

@Mock
private Configuration configuration;

@Mock
private Video video;

@Mock
private TestData testData;

@Mock
private Path videoPath;

@Mock
private Video.ExtentTest videoExtentTest;

@InjectMocks
private ExtentTestResolver extentTestResolver;

Expand Down Expand Up @@ -100,9 +120,20 @@ public void getColorOf(final Status status, final ExtentColor expected) {
assertEquals(expected, ExtentTestResolver.getColorOf(status));
}

public static Stream<Arguments> valuesProvider() {
return Stream.of(
arguments(FAIL, RED),
arguments(SKIP, AMBER),
arguments(INFO, GREEN)
);
}

@Test
@DisplayName("resolveParameter should return the initialized ExtentTest")
@DisplayName("resolveParameter should return the initialized ExtentTest adding the video")
public void testResolveParameter() {
final int width = 123;
final int height = 456;

// createExtentTestFrom
when(SpectrumSessionListener.getExtentReports()).thenReturn(extentReports);
when(extensionContext.getStore(GLOBAL)).thenReturn(store);
Expand All @@ -111,10 +142,20 @@ public void testResolveParameter() {
when(parentContext.getDisplayName()).thenReturn(className);
when(extentReports.createTest(String.format("<div id=\"%s\">%s</div>%s", transformedTestName, className, displayName))).thenReturn(extentTest);

when(extentTest.info(any(Markup.class))).thenReturn(extentTest);
when(store.get(CONFIGURATION, Configuration.class)).thenReturn(configuration);
when(configuration.getVideo()).thenReturn(video);
when(video.isDisabled()).thenReturn(false);
when(video.getExtentTest()).thenReturn(videoExtentTest);
when(videoExtentTest.isAttach()).thenReturn(true);
when(videoExtentTest.getWidth()).thenReturn(width);
when(videoExtentTest.getHeight()).thenReturn(height);
when(store.get(TEST_DATA, TestData.class)).thenReturn(testData);
when(testData.getVideoPath()).thenReturn(videoPath);

ExtentTest actual = extentTestResolver.resolveParameter(parameterContext, extensionContext);

verify(extentTest).info(String.format("<video controls width=\"%d\" height=\"%d\" src=\"%s\" type=\"video/mp4\"/>", width, height, videoPath));

ArgumentCaptor<Markup> markupArgumentCaptor = ArgumentCaptor.forClass(Markup.class);
verify(extentTest).info(markupArgumentCaptor.capture());
Markup markup = markupArgumentCaptor.getValue();
Expand All @@ -124,11 +165,44 @@ public void testResolveParameter() {
assertEquals(extentTest, actual);
}

public static Stream<Arguments> valuesProvider() {
@DisplayName("resolveParameter should return the initialized ExtentTest without adding the video")
@ParameterizedTest(name = "with video disabled {0} and video attach {1}")
@MethodSource("noVideoValuesProvider")
public void testResolveParameterNoVideo(final boolean disabled, final boolean attach) {
// createExtentTestFrom
when(SpectrumSessionListener.getExtentReports()).thenReturn(extentReports);
when(extensionContext.getStore(GLOBAL)).thenReturn(store);
when(extensionContext.getDisplayName()).thenReturn(displayName);
when(extensionContext.getParent()).thenReturn(Optional.of(parentContext));
when(parentContext.getDisplayName()).thenReturn(className);
when(extentReports.createTest(String.format("<div id=\"%s\">%s</div>%s", transformedTestName, className, displayName))).thenReturn(extentTest);

when(store.get(CONFIGURATION, Configuration.class)).thenReturn(configuration);
when(configuration.getVideo()).thenReturn(video);
when(video.isDisabled()).thenReturn(disabled);
when(video.getExtentTest()).thenReturn(videoExtentTest);

if (!disabled) { // short-circuit
when(videoExtentTest.isAttach()).thenReturn(attach);
}

ExtentTest actual = extentTestResolver.resolveParameter(parameterContext, extensionContext);

ArgumentCaptor<Markup> markupArgumentCaptor = ArgumentCaptor.forClass(Markup.class);
verify(extentTest).info(markupArgumentCaptor.capture());
Markup markup = markupArgumentCaptor.getValue();
assertEquals(createLabel("START TEST", GREEN).getMarkup(), markup.getMarkup());
verifyNoMoreInteractions(extentTest);

verify(store).put(ExtentTestResolver.EXTENT_TEST, actual);
assertEquals(extentTest, actual);
}

public static Stream<Arguments> noVideoValuesProvider() {
return Stream.of(
arguments(FAIL, RED),
arguments(SKIP, AMBER),
arguments(INFO, GREEN)
arguments(true, false),
arguments(true, false),
arguments(true, true)
);
}
}
Loading

0 comments on commit 22b1300

Please sign in to comment.