├── .classpath ├── .gitignore ├── .project ├── .travis.yml ├── ISSUE_TEMPLATE.md ├── README.md ├── dist ├── css │ └── extent.css └── js │ └── extent.js ├── doc ├── allclasses-frame.html ├── allclasses-noframe.html ├── com │ └── aventstack │ │ └── extentreports │ │ ├── AnalysisStrategy.html │ │ ├── App.html │ │ ├── Base.html │ │ ├── ExceptionTestContextImpl.html │ │ ├── ExtentReporter.html │ │ ├── ExtentReports.html │ │ ├── ExtentTest.html │ │ ├── ExtentTestInterruptedException.html │ │ ├── GherkinKeyword.html │ │ ├── IAnalysisStrategy.html │ │ ├── IReport.html │ │ ├── InvalidFileException.html │ │ ├── MediaEntityBuilder.html │ │ ├── MediaEntityModelProvider.html │ │ ├── ParallelClass1.html │ │ ├── ParallelClass2.html │ │ ├── ParallelClassesBase.html │ │ ├── ParallelMethods.html │ │ ├── ReportAggregatesListener.html │ │ ├── ReportConfigurator.html │ │ ├── ResourceCDN.html │ │ ├── RunResult.html │ │ ├── SessionStatusStats.html │ │ ├── Status.html │ │ ├── StatusConfigurator.html │ │ ├── SystemAttributeContext.html │ │ ├── TestAttributeTestContextProvider.html │ │ ├── TestListener.html │ │ ├── api │ │ ├── BddAttributesTest.html │ │ ├── BddLevelsTests.html │ │ ├── BddWithStepStatusHierarchyTests.html │ │ ├── BuildReportWithoutAttachedReportersTests.html │ │ ├── BuildsReportWithoutTests.html │ │ ├── GherkinKeywordTests.html │ │ ├── NodeAttributesTest.html │ │ ├── NodeMediaTests.html │ │ ├── NodeSingleLogsStatusTests.html │ │ ├── NodeWithoutLogs.html │ │ ├── NodesStatusHierarchyTests.html │ │ ├── StatusHierarchyConfiguratorTests.html │ │ ├── TestAttributesTests.html │ │ ├── TestIdsTests.html │ │ ├── TestInitializeNullValuesTests.html │ │ ├── TestMediaTests.html │ │ ├── TestSingleLogsStatusTests.html │ │ ├── TestStartEndDateTimeTests.html │ │ ├── TestStatusHierarchyTests.html │ │ ├── TestWithoutLogs.html │ │ ├── class-use │ │ │ ├── BddAttributesTest.html │ │ │ ├── BddLevelsTests.html │ │ │ ├── BddWithStepStatusHierarchyTests.html │ │ │ ├── BuildReportWithoutAttachedReportersTests.html │ │ │ ├── BuildsReportWithoutTests.html │ │ │ ├── GherkinKeywordTests.html │ │ │ ├── NodeAttributesTest.html │ │ │ ├── NodeMediaTests.html │ │ │ ├── NodeSingleLogsStatusTests.html │ │ │ ├── NodeWithoutLogs.html │ │ │ ├── NodesStatusHierarchyTests.html │ │ │ ├── StatusHierarchyConfiguratorTests.html │ │ │ ├── TestAttributesTests.html │ │ │ ├── TestIdsTests.html │ │ │ ├── TestInitializeNullValuesTests.html │ │ │ ├── TestMediaTests.html │ │ │ ├── TestSingleLogsStatusTests.html │ │ │ ├── TestStartEndDateTimeTests.html │ │ │ ├── TestStatusHierarchyTests.html │ │ │ └── TestWithoutLogs.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ │ ├── class-use │ │ ├── AnalysisStrategy.html │ │ ├── App.html │ │ ├── Base.html │ │ ├── ExceptionTestContextImpl.html │ │ ├── ExtentReporter.html │ │ ├── ExtentReports.html │ │ ├── ExtentTest.html │ │ ├── ExtentTestInterruptedException.html │ │ ├── GherkinKeyword.html │ │ ├── IAnalysisStrategy.html │ │ ├── IReport.html │ │ ├── InvalidFileException.html │ │ ├── MediaEntityBuilder.html │ │ ├── MediaEntityModelProvider.html │ │ ├── ParallelClass1.html │ │ ├── ParallelClass2.html │ │ ├── ParallelClassesBase.html │ │ ├── ParallelMethods.html │ │ ├── ReportAggregatesListener.html │ │ ├── ReportConfigurator.html │ │ ├── ResourceCDN.html │ │ ├── RunResult.html │ │ ├── SessionStatusStats.html │ │ ├── Status.html │ │ ├── StatusConfigurator.html │ │ ├── SystemAttributeContext.html │ │ ├── TestAttributeTestContextProvider.html │ │ └── TestListener.html │ │ ├── common │ │ ├── ExtentManager.html │ │ ├── ExtentTestManager.html │ │ ├── ExtentTestNGIReporterListener.html │ │ ├── ExtentTestNGITestListener.html │ │ ├── ExtentTestNGListener.html │ │ ├── class-use │ │ │ ├── ExtentManager.html │ │ │ ├── ExtentTestManager.html │ │ │ ├── ExtentTestNGIReporterListener.html │ │ │ ├── ExtentTestNGITestListener.html │ │ │ └── ExtentTestNGListener.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ │ ├── configuration │ │ ├── Config.html │ │ ├── ConfigLoader.html │ │ ├── ConfigMap.html │ │ ├── class-use │ │ │ ├── Config.html │ │ │ ├── ConfigLoader.html │ │ │ └── ConfigMap.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ │ ├── gherkin │ │ ├── GherkinDialect.html │ │ ├── GherkinDialectProvider.html │ │ ├── class-use │ │ │ ├── GherkinDialect.html │ │ │ └── GherkinDialectProvider.html │ │ ├── model │ │ │ ├── And.html │ │ │ ├── Background.html │ │ │ ├── Feature.html │ │ │ ├── Given.html │ │ │ ├── IGherkinFormatterModel.html │ │ │ ├── Scenario.html │ │ │ ├── ScenarioOutline.html │ │ │ ├── Then.html │ │ │ ├── When.html │ │ │ ├── class-use │ │ │ │ ├── And.html │ │ │ │ ├── Background.html │ │ │ │ ├── Feature.html │ │ │ │ ├── Given.html │ │ │ │ ├── IGherkinFormatterModel.html │ │ │ │ ├── Scenario.html │ │ │ │ ├── ScenarioOutline.html │ │ │ │ ├── Then.html │ │ │ │ └── When.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── package-use.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ │ ├── listenertests │ │ ├── ListenerTests.html │ │ ├── ListenerTestsIReporter.html │ │ ├── ListenerTestsITestListener.html │ │ ├── class-use │ │ │ ├── ListenerTests.html │ │ │ ├── ListenerTestsIReporter.html │ │ │ └── ListenerTestsITestListener.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ │ ├── markuputils │ │ ├── ExtentColor.html │ │ ├── Markup.html │ │ ├── MarkupHelper.html │ │ ├── class-use │ │ │ ├── ExtentColor.html │ │ │ ├── Markup.html │ │ │ └── MarkupHelper.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ │ ├── mediastorage │ │ ├── MediaStorage.html │ │ ├── MediaStorageManagerFactory.html │ │ ├── class-use │ │ │ ├── MediaStorage.html │ │ │ └── MediaStorageManagerFactory.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ │ ├── model │ │ ├── AbstractStructure.html │ │ ├── Author.html │ │ ├── BasicReportElement.html │ │ ├── Category.html │ │ ├── ExceptionInfo.html │ │ ├── ExceptionTestContext.html │ │ ├── IAddsMedia.html │ │ ├── Log.html │ │ ├── LogStructure.html │ │ ├── Media.html │ │ ├── MediaType.html │ │ ├── NodeStructure.html │ │ ├── ScreenCapture.html │ │ ├── Screencast.html │ │ ├── SystemAttribute.html │ │ ├── Test.html │ │ ├── TestAttribute.html │ │ ├── TestAttributeTestContext.html │ │ ├── class-use │ │ │ ├── AbstractStructure.html │ │ │ ├── Author.html │ │ │ ├── BasicReportElement.html │ │ │ ├── Category.html │ │ │ ├── ExceptionInfo.html │ │ │ ├── ExceptionTestContext.html │ │ │ ├── IAddsMedia.html │ │ │ ├── Log.html │ │ │ ├── LogStructure.html │ │ │ ├── Media.html │ │ │ ├── MediaType.html │ │ │ ├── NodeStructure.html │ │ │ ├── ScreenCapture.html │ │ │ ├── Screencast.html │ │ │ ├── SystemAttribute.html │ │ │ ├── Test.html │ │ │ ├── TestAttribute.html │ │ │ └── TestAttributeTestContext.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ ├── package-use.html │ │ ├── reporter │ │ ├── AbstractReporter.html │ │ ├── BasicFileReporter.html │ │ ├── ExtentHtmlReporter.html │ │ ├── ExtentXReporter.html │ │ ├── ReportAppendable.html │ │ ├── class-use │ │ │ ├── AbstractReporter.html │ │ │ ├── BasicFileReporter.html │ │ │ ├── ExtentHtmlReporter.html │ │ │ ├── ExtentXReporter.html │ │ │ └── ReportAppendable.html │ │ ├── configuration │ │ │ ├── BasicFileConfiguration.html │ │ │ ├── ChartLocation.html │ │ │ ├── ExtentHtmlReporterConfiguration.html │ │ │ ├── ExtentXReporterConfiguration.html │ │ │ ├── IReporterConfiguration.html │ │ │ ├── Protocol.html │ │ │ ├── Theme.html │ │ │ ├── class-use │ │ │ │ ├── BasicFileConfiguration.html │ │ │ │ ├── ChartLocation.html │ │ │ │ ├── ExtentHtmlReporterConfiguration.html │ │ │ │ ├── ExtentXReporterConfiguration.html │ │ │ │ ├── IReporterConfiguration.html │ │ │ │ ├── Protocol.html │ │ │ │ └── Theme.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── package-use.html │ │ ├── converters │ │ │ ├── ExtentHtmlBddNodesConverter.html │ │ │ ├── ExtentHtmlLogConverter.html │ │ │ ├── ExtentHtmlReporterConverter.html │ │ │ ├── class-use │ │ │ │ ├── ExtentHtmlBddNodesConverter.html │ │ │ │ ├── ExtentHtmlLogConverter.html │ │ │ │ └── ExtentHtmlReporterConverter.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── package-use.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ │ ├── testng │ │ └── components │ │ │ ├── ExtentTestNGReportBuilder.html │ │ │ ├── ParallelTest1.html │ │ │ ├── ParallelTest2.html │ │ │ ├── class-use │ │ │ ├── ExtentTestNGReportBuilder.html │ │ │ ├── ParallelTest1.html │ │ │ └── ParallelTest2.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── package-use.html │ │ ├── utils │ │ ├── DateUtil.html │ │ ├── ExceptionUtil.html │ │ ├── FileUtil.html │ │ ├── MongoUtil.html │ │ ├── Reader.html │ │ ├── StringUtil.html │ │ ├── Writer.html │ │ ├── class-use │ │ │ ├── DateUtil.html │ │ │ ├── ExceptionUtil.html │ │ │ ├── FileUtil.html │ │ │ ├── MongoUtil.html │ │ │ ├── Reader.html │ │ │ ├── StringUtil.html │ │ │ └── Writer.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html │ │ ├── view │ │ └── extenthtml │ │ │ ├── AuthorViewVisibilityTests.html │ │ │ ├── BugViewVisibilityTests.html │ │ │ ├── CategoryViewVisibilityTests.html │ │ │ ├── ChartsVisibilityTests.html │ │ │ ├── SystemAttributeTests.html │ │ │ ├── TestAndNodeAttributesTest.html │ │ │ ├── TestAttributesTest.html │ │ │ ├── TestMarkupTest.html │ │ │ ├── TestWithoutLogsHasPassStatus.html │ │ │ ├── class-use │ │ │ ├── AuthorViewVisibilityTests.html │ │ │ ├── BugViewVisibilityTests.html │ │ │ ├── CategoryViewVisibilityTests.html │ │ │ ├── ChartsVisibilityTests.html │ │ │ ├── SystemAttributeTests.html │ │ │ ├── TestAndNodeAttributesTest.html │ │ │ ├── TestAttributesTest.html │ │ │ ├── TestMarkupTest.html │ │ │ └── TestWithoutLogsHasPassStatus.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── package-use.html │ │ └── viewdefs │ │ ├── Icon.html │ │ ├── class-use │ │ └── Icon.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── package-use.html ├── constant-values.html ├── deprecated-list.html ├── help-doc.html ├── index-files │ ├── index-1.html │ ├── index-10.html │ ├── index-11.html │ ├── index-12.html │ ├── index-13.html │ ├── index-14.html │ ├── index-15.html │ ├── index-16.html │ ├── index-17.html │ ├── index-18.html │ ├── index-19.html │ ├── index-2.html │ ├── index-20.html │ ├── index-3.html │ ├── index-4.html │ ├── index-5.html │ ├── index-6.html │ ├── index-7.html │ ├── index-8.html │ └── index-9.html ├── index.html ├── overview-frame.html ├── overview-summary.html ├── overview-tree.html ├── package-list ├── script.js ├── serialized-form.html └── stylesheet.css ├── extent-config.xml ├── license ├── pom-nexus.xml ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── aventstack │ │ └── extentreports │ │ ├── AbstractProcessor.java │ │ ├── AnalysisStrategy.java │ │ ├── AnalysisTypeConfigurable.java │ │ ├── ExtentReports.java │ │ ├── ExtentTest.java │ │ ├── GherkinKeyword.java │ │ ├── GherkinKeywordNotFoundException.java │ │ ├── Main.java │ │ ├── MediaEntityBuilder.java │ │ ├── NullStatusException.java │ │ ├── NullTestException.java │ │ ├── ProvidesSource.java │ │ ├── ReactiveSubject.java │ │ ├── Status.java │ │ ├── Writable.java │ │ ├── annotations │ │ ├── MarkupIgnore.java │ │ └── MarkupInclude.java │ │ ├── append │ │ ├── JsonDeserializer.java │ │ ├── RawEntityConverter.java │ │ └── ScreenCaptureTypeAdapter.java │ │ ├── config │ │ ├── ConfigStore.java │ │ └── external │ │ │ ├── CaseInsensitiveEnumTypeAdapterFactory.java │ │ │ ├── ConfigLoadable.java │ │ │ ├── JsonConfigLoader.java │ │ │ └── XmlConfigLoader.java │ │ ├── gherkin │ │ ├── GherkinDialect.java │ │ ├── GherkinDialectManager.java │ │ └── model │ │ │ ├── And.java │ │ │ ├── Asterisk.java │ │ │ ├── Background.java │ │ │ ├── But.java │ │ │ ├── Feature.java │ │ │ ├── GherkinEntity.java │ │ │ ├── Given.java │ │ │ ├── IGherkinFormatterModel.java │ │ │ ├── Scenario.java │ │ │ ├── ScenarioOutline.java │ │ │ ├── Then.java │ │ │ └── When.java │ │ ├── io │ │ └── BufferedWriterWriter.java │ │ ├── markuputils │ │ ├── CodeBlock.java │ │ ├── CodeLanguage.java │ │ ├── ExtentColor.java │ │ ├── HtmlList.java │ │ ├── Label.java │ │ ├── ListType.java │ │ ├── Markup.java │ │ ├── MarkupHelper.java │ │ ├── MarkupTemplate.java │ │ ├── OrderedList.java │ │ ├── Table.java │ │ ├── UnorderedList.java │ │ └── util │ │ │ └── ReflectionUtil.java │ │ ├── model │ │ ├── Author.java │ │ ├── BaseEntity.java │ │ ├── Category.java │ │ ├── Device.java │ │ ├── ExceptionInfo.java │ │ ├── Log.java │ │ ├── Media.java │ │ ├── NameValuePair.java │ │ ├── NamedAttribute.java │ │ ├── Report.java │ │ ├── ReportStats.java │ │ ├── RunResult.java │ │ ├── ScreenCapture.java │ │ ├── SystemEnvInfo.java │ │ ├── Test.java │ │ ├── context │ │ │ ├── NamedAttributeContext.java │ │ │ ├── NamedAttributeContextManager.java │ │ │ └── filter │ │ │ │ └── NamedAttributeTestContextFilter.java │ │ └── service │ │ │ ├── EntityService.java │ │ │ ├── ExceptionInfoService.java │ │ │ ├── MediaService.java │ │ │ ├── ReportFilterService.java │ │ │ ├── TestService.java │ │ │ └── util │ │ │ └── ExceptionUtil.java │ │ ├── observable │ │ └── ObservableList.java │ │ ├── observer │ │ ├── AttributesObserver.java │ │ ├── EntityObserver.java │ │ ├── ExtentObserver.java │ │ ├── LogObserver.java │ │ ├── MediaObserver.java │ │ ├── ReportObserver.java │ │ ├── TestObserver.java │ │ └── entity │ │ │ ├── AttributeEntity.java │ │ │ ├── LogEntity.java │ │ │ ├── MediaEntity.java │ │ │ ├── NamedAttributeTestEntity.java │ │ │ ├── ObservedEntity.java │ │ │ ├── ReportEntity.java │ │ │ └── TestEntity.java │ │ ├── reporter │ │ ├── AbstractFileReporter.java │ │ ├── AbstractFilterableReporter.java │ │ ├── AbstractReporter.java │ │ ├── ExtentKlovReporter.java │ │ ├── ExtentReporter.java │ │ ├── ExtentSparkReporter.java │ │ ├── JsonFormatter.java │ │ ├── ReporterConfigurable.java │ │ ├── ReporterFilterable.java │ │ ├── configuration │ │ │ ├── AbstractConfiguration.java │ │ │ ├── EntityFilters.java │ │ │ ├── ExtentSparkReporterConfig.java │ │ │ ├── FileReporterConfig.java │ │ │ ├── InteractiveReporterConfig.java │ │ │ ├── Protocol.java │ │ │ ├── StatusFilter.java │ │ │ ├── Theme.java │ │ │ ├── ViewConfigurer.java │ │ │ ├── ViewName.java │ │ │ ├── ViewOrder.java │ │ │ ├── ViewStyle.java │ │ │ ├── ViewsConfigurable.java │ │ │ └── util │ │ │ │ ├── IOUtil.java │ │ │ │ └── ResourceHelper.java │ │ ├── filter │ │ │ ├── ContextFilter.java │ │ │ └── StatusFilterable.java │ │ └── klov │ │ │ ├── KlovReporterClient.java │ │ │ ├── entity │ │ │ ├── KlovAttribute.java │ │ │ ├── KlovAuthor.java │ │ │ ├── KlovCategory.java │ │ │ ├── KlovDevice.java │ │ │ ├── KlovEntity.java │ │ │ ├── KlovEnvironment.java │ │ │ ├── KlovExceptionEvent.java │ │ │ ├── KlovLog.java │ │ │ ├── KlovMedia.java │ │ │ ├── KlovProject.java │ │ │ ├── KlovReport.java │ │ │ ├── KlovTest.java │ │ │ └── KlovURI.java │ │ │ └── util │ │ │ └── URIUtil.java │ │ ├── templating │ │ ├── FreemarkerTemplate.java │ │ └── TemplateConfig.java │ │ └── view │ │ └── Ico.java └── resources │ └── com │ └── aventstack │ └── extentreports │ ├── gherkin │ └── gherkin-languages.json │ ├── markup │ ├── codeblock.ftl │ └── codeblock.json.ftl │ ├── offline │ ├── commons │ │ ├── css │ │ │ └── icons │ │ │ │ ├── font-awesome.min.css │ │ │ │ └── fontawesome │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ └── fontawesome-webfont.woff2 │ │ ├── img │ │ │ └── logo.png │ │ └── js │ │ │ └── jsontree.js │ └── spark │ │ ├── css │ │ └── spark-style.css │ │ └── js │ │ └── spark-script.js │ └── templates │ ├── commons │ ├── commons-dashboard-scripts.ftl │ ├── commons-dashboard.ftl │ ├── commons-exception.ftl │ ├── commons-inject-css.ftl │ ├── commons-inject-js.ftl │ ├── commons-macros.ftl │ ├── commons-tag.ftl │ └── commons-variables.ftl │ └── spark │ ├── dashboard.ftl │ ├── exception.ftl │ ├── macros │ ├── attributes.ftl │ ├── log.ftl │ └── recurse_nodes.ftl │ ├── partials │ ├── author.ftl │ ├── bdd-content.ftl │ ├── category.ftl │ ├── dashboard.ftl │ ├── device.ftl │ ├── exception.ftl │ ├── head.ftl │ ├── log.ftl │ ├── logs.ftl │ ├── navbar.ftl │ ├── scripts.ftl │ ├── sidenav.ftl │ ├── standard-content.ftl │ └── test.ftl │ ├── spark.spa.ftl │ ├── tag.ftl │ └── test.ftl └── test ├── java └── com │ └── aventstack │ └── extentreports │ ├── AppenderTest.java │ ├── BddTypeTest.java │ ├── ExtentReportsTest.java │ ├── ExtentTestLogHierarchyTest.java │ ├── ExtentTestLogTest.java │ ├── ExtentTestMediaTest.java │ ├── ExtentTestNodeTest.java │ ├── NaturalConfTest.java │ ├── ObserverTest.java │ ├── ParallelTest.java │ ├── TestIdsTest.java │ ├── config │ ├── ConfigStoreTest.java │ └── external │ │ ├── JsonConfigLoaderTest.java │ │ └── XmlConfigLoaderTest.java │ ├── entity │ ├── AuthorEntityTest.java │ ├── CategoryEntityTest.java │ ├── DeviceEntityTest.java │ ├── LogEntityTest.java │ ├── ReportEntityTest.java │ ├── ReportStatsTest.java │ ├── ScreenCaptureTest.java │ ├── StatusEntityTest.java │ ├── TestEntityInitTest.java │ ├── TestEntityTest.java │ └── service │ │ ├── ExceptionInfoServiceTest.java │ │ └── TestServiceTest.java │ ├── gherkin │ ├── GherkinKeywordTest.java │ └── GherkinNameTest.java │ ├── markuputils │ ├── CodeBlockMarkupTest.java │ ├── Foo.java │ ├── LabelMarkupTest.java │ ├── ListTest.java │ └── TableMarkupTest.java │ ├── observer │ └── ReportEntityObserverTest.java │ └── reporter │ └── SparkReporterTest.java └── resources ├── config ├── spark-config.json ├── spark-config.xml ├── spark-config_lowercase_enum.json └── spark-config_lowercase_enum.xml └── img.png /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.db 2 | *.db 3 | *.jar 4 | *.lst 5 | *.iml 6 | *.idea 7 | uiDesigner.xml 8 | .vscode/launch.json 9 | /target/ 10 | test-output/ 11 | /.idea/ 12 | .settings/ 13 | extent.html 14 | .project 15 | .classpath 16 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | extentreports 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | services: 5 | - mongodb -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | ## Summary 6 | 7 | 8 | 9 | ## Expected Behavior 10 | 11 | 12 | 13 | 14 | ## Current Behavior 15 | 16 | 17 | 18 | 19 | ## Sample 20 | 21 | 22 | ```java 23 | // Sample code goes here 24 | ``` 25 | 26 | ## Environment Details 27 | 28 | 29 | * Extent report Version used: 30 | * Operating System and version: 31 | * JDK Version: 32 | 33 | ## Screenshots 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Important 2 | 3 | With the release of version 4, the official repository for [Extent Framework](https://github.com/extent-framework) project has moved to its [dedicated org](https://github.com/extent-framework). 4 | 5 | 6 | ## ExtentAPI 3 Java 7 | 8 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/657a54f85e59482da4310c72af5e5182)](https://www.codacy.com/app/anshooarora/extentreports-java?utm_source=github.com&utm_medium=referral&utm_content=anshooarora/extentreports-java&utm_campaign=badger) 9 | [![Join the chat at https://gitter.im/anshooarora/extentreports](https://badges.gitter.im/anshooarora/extentreports.svg)](https://gitter.im/anshooarora/extentreports?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 10 | [![Build Status](https://travis-ci.org/anshooarora/extentreports-java.svg)](https://travis-ci.org/anshooarora/extentreports-java) [![Maven Central](https://img.shields.io/maven-central/v/com.aventstack/extentreports.svg?maxAge=300)](http://search.maven.org/#search|ga|1|g:"com.aventstack") 11 | 12 | This version is Java8 only. Version 2 and lower are no longer supported. 13 | 14 | [Klov](https://github.com/anshooarora/klov) report server is supported with version 3.1.0+. 15 | 16 | > Note: ExtentX is deprecated, please use Klov instead. 17 | 18 | ### Documentation 19 | 20 | View [extentreports.com](http://extentreports.com/docs/versions/3/java/) for complete documentation. 21 | 22 | ### Samples 23 | 24 | * Standard 25 | * BDD 26 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/common/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.common 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.common

13 |
14 |

Classes

15 | 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/configuration/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.configuration 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.configuration

13 |
14 |

Classes

15 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/gherkin/model/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.gherkin.model 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.gherkin.model

13 |
14 |

Interfaces

15 | 18 |

Classes

19 | 29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/gherkin/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.gherkin 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.gherkin

13 |
14 |

Classes

15 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/listenertests/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.listenertests 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.listenertests

13 |
14 |

Classes

15 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/markuputils/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.markuputils 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.markuputils

13 |
14 |

Interfaces

15 | 18 |

Classes

19 | 22 |

Enums

23 | 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/mediastorage/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.mediastorage 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.mediastorage

13 |
14 |

Interfaces

15 | 18 |

Classes

19 | 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/model/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.model 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.model

13 |
14 |

Interfaces

15 | 19 |

Classes

20 | 35 |

Enums

36 | 39 |
40 | 41 | 42 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/reporter/configuration/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.reporter.configuration 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.reporter.configuration

13 |
14 |

Interfaces

15 | 18 |

Classes

19 | 24 |

Enums

25 | 30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/reporter/converters/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.reporter.converters 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.reporter.converters

13 |
14 |

Classes

15 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/reporter/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.reporter 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.reporter

13 |
14 |

Interfaces

15 | 18 |

Classes

19 | 25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/testng/components/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.testng.components 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.testng.components

13 |
14 |

Classes

15 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/utils/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.utils 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.utils

13 |
14 |

Classes

15 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/view/extenthtml/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.view.extenthtml 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.view.extenthtml

13 |
14 |

Classes

15 | 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /doc/com/aventstack/extentreports/viewdefs/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | com.aventstack.extentreports.viewdefs 7 | 8 | 9 | 10 | 11 | 12 |

com.aventstack.extentreports.viewdefs

13 |
14 |

Classes

15 | 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Generated Documentation (Untitled) 7 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | <noscript> 68 | <div>JavaScript is disabled on your browser.</div> 69 | </noscript> 70 | <h2>Frame Alert</h2> 71 | <p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="overview-summary.html">Non-frame version</a>.</p> 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /doc/package-list: -------------------------------------------------------------------------------- 1 | com.aventstack.extentreports 2 | com.aventstack.extentreports.api 3 | com.aventstack.extentreports.common 4 | com.aventstack.extentreports.configuration 5 | com.aventstack.extentreports.gherkin 6 | com.aventstack.extentreports.gherkin.model 7 | com.aventstack.extentreports.listenertests 8 | com.aventstack.extentreports.markuputils 9 | com.aventstack.extentreports.mediastorage 10 | com.aventstack.extentreports.model 11 | com.aventstack.extentreports.reporter 12 | com.aventstack.extentreports.reporter.configuration 13 | com.aventstack.extentreports.reporter.converters 14 | com.aventstack.extentreports.testng.components 15 | com.aventstack.extentreports.utils 16 | com.aventstack.extentreports.view.extenthtml 17 | com.aventstack.extentreports.viewdefs 18 | -------------------------------------------------------------------------------- /doc/script.js: -------------------------------------------------------------------------------- 1 | function show(type) 2 | { 3 | count = 0; 4 | for (var key in methods) { 5 | var row = document.getElementById(key); 6 | if ((methods[key] & type) != 0) { 7 | row.style.display = ''; 8 | row.className = (count++ % 2) ? rowColor : altColor; 9 | } 10 | else 11 | row.style.display = 'none'; 12 | } 13 | updateTabs(type); 14 | } 15 | 16 | function updateTabs(type) 17 | { 18 | for (var value in tabs) { 19 | var sNode = document.getElementById(tabs[value][0]); 20 | var spanNode = sNode.firstChild; 21 | if (value == type) { 22 | sNode.className = activeTableTab; 23 | spanNode.innerHTML = tabs[value][1]; 24 | } 25 | else { 26 | sNode.className = tableTab; 27 | spanNode.innerHTML = "" + tabs[value][1] + ""; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /extent-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | standard 7 | 8 | 9 | 10 | UTF-8 11 | 12 | 13 | 14 | https 15 | 16 | 17 | Extent 18 | 19 | 20 | Automation Report 21 | 22 | 23 | 24 | bottom 25 | 26 | 27 | 28 | 33 | 34 | 35 | 36 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | ExtentReports Community Version 2 | 3 | Copyright 2016 AventStack 4 | 5 | The BSD 3-Clause License: http://opensource.org/licenses/BSD-3-Clause 6 | 7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL aventstack.com BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/AnalysisStrategy.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | import com.aventstack.extentreports.gherkin.model.IGherkinFormatterModel; 4 | import com.aventstack.extentreports.model.ReportStats; 5 | 6 | /** 7 | * Enumeration for various kinds of analysis strategies used by 8 | * {@link ReportStats} 9 | */ 10 | public enum AnalysisStrategy { 11 | /** 12 | * This is the efault strategy used by BDD tests. If any created test uses a 13 | * {@link IGherkinFormatterModel} type, the strategy would default to BDD 14 | * and {@link AnalysisStrategy} would be ignored. 15 | */ 16 | BDD, 17 | 18 | /** 19 | * This strategy is useful when all tests in a suite are grouped together by 20 | * their containing Class. This strategy would account for the number of 21 | * Classes that passed or failed, and repeat the process for tests. 22 | */ 23 | CLASS, 24 | 25 | /** 26 | * This strategy is useful if there are 3 levels in the hierarchy: Suite, 27 | * Class and Test. 28 | */ 29 | SUITE, 30 | 31 | /** 32 | * TEST is the default strategy and only tracks the leaf nodes to create 33 | * {@link ReportStats} 34 | */ 35 | TEST 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/AnalysisTypeConfigurable.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | @FunctionalInterface 4 | public interface AnalysisTypeConfigurable { 5 | void setAnalysisStrategy(AnalysisStrategy strategy); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/GherkinKeywordNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | public class GherkinKeywordNotFoundException extends ClassNotFoundException { 4 | private static final long serialVersionUID = 3140022717738862603L; 5 | 6 | public GherkinKeywordNotFoundException(String message) { 7 | super(message); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/MediaEntityBuilder.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | import com.aventstack.extentreports.model.Media; 4 | import com.aventstack.extentreports.model.ScreenCapture; 5 | 6 | /** 7 | * Media builder for base64 and binary screenshots 8 | * 9 | */ 10 | public class MediaEntityBuilder { 11 | private static final String BASE64_ENCODED = "data:image/png;base64,"; 12 | private static ThreadLocal media = new ThreadLocal<>(); 13 | 14 | private static class MediaBuilderInstance { 15 | static final MediaEntityBuilder INSTANCE = new MediaEntityBuilder(); 16 | 17 | private MediaBuilderInstance() { 18 | } 19 | } 20 | 21 | private MediaEntityBuilder() { 22 | } 23 | 24 | private static synchronized MediaEntityBuilder getInstance() { 25 | return MediaBuilderInstance.INSTANCE; 26 | } 27 | 28 | public Media build() { 29 | return media.get(); 30 | } 31 | 32 | public static MediaEntityBuilder createScreenCaptureFromPath(String path, String title) { 33 | if (path == null || path.isEmpty()) 34 | throw new IllegalArgumentException("ScreenCapture path cannot be null or empty"); 35 | media.set(ScreenCapture.builder().path(path).title(title).build()); 36 | return getInstance(); 37 | } 38 | 39 | public static MediaEntityBuilder createScreenCaptureFromPath(String path) { 40 | return createScreenCaptureFromPath(path, null); 41 | } 42 | 43 | public static MediaEntityBuilder createScreenCaptureFromBase64String(String base64, String title) { 44 | if (base64 == null || base64.trim().equals("")) 45 | throw new IllegalArgumentException("Base64 string cannot be null or empty"); 46 | if (!base64.startsWith("data:")) 47 | base64 = BASE64_ENCODED + base64; 48 | media.set(ScreenCapture.builder().base64(base64).title(title).build()); 49 | return getInstance(); 50 | } 51 | 52 | public static MediaEntityBuilder createScreenCaptureFromBase64String(String base64) { 53 | return createScreenCaptureFromBase64String(base64, null); 54 | } 55 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/NullStatusException.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | public class NullStatusException extends NullPointerException { 4 | private static final long serialVersionUID = 3331364668564936293L; 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/NullTestException.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | public class NullTestException extends NullPointerException { 4 | private static final long serialVersionUID = -2987170430890267069L; 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/ProvidesSource.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | public interface ProvidesSource { 4 | String getSource(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/Status.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.Comparator; 6 | import java.util.List; 7 | 8 | import com.aventstack.extentreports.view.Ico; 9 | 10 | import lombok.Getter; 11 | 12 | @Getter 13 | public enum Status { 14 | INFO("Info", 10), PASS("Pass", 20), SKIP("Skip", 30), WARNING("Warning", 40), FAIL("Fail", 50); 15 | 16 | private final Integer level; 17 | private final String name; 18 | 19 | Status(String name, Integer level) { 20 | this.name = name; 21 | this.level = level; 22 | } 23 | 24 | private static void resolveHierarchy(List status) { 25 | status.sort((Status s1, Status s2) -> s1.getLevel().compareTo(s2.getLevel())); 26 | } 27 | 28 | public static List getResolvedHierarchy(List status) { 29 | List list = new ArrayList<>(status); 30 | resolveHierarchy(list); 31 | return list; 32 | } 33 | 34 | public static Status max(Collection status) { 35 | return status.stream().max(Comparator.comparing(Status::getLevel)).orElse(PASS); 36 | } 37 | 38 | public static Status max(Status s1, Status s2) { 39 | return s1.getLevel() > s2.getLevel() ? s1 : s2; 40 | } 41 | 42 | public static Status min(Collection status) { 43 | return status.stream().min(Comparator.comparing(Status::getLevel)).orElse(PASS); 44 | } 45 | 46 | public static String i(String status) { 47 | return Ico.ico(status).toString(); 48 | } 49 | 50 | public static String i(Status status) { 51 | return Ico.ico(status.toString()).toString(); 52 | } 53 | 54 | public String toLower() { 55 | return name.toLowerCase(); 56 | } 57 | 58 | @Override 59 | public String toString() { 60 | return name; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/Writable.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | @FunctionalInterface 4 | public interface Writable { 5 | void flush(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/annotations/MarkupIgnore.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.annotations; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.FIELD) 10 | public @interface MarkupIgnore { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/annotations/MarkupInclude.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.annotations; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.FIELD) 10 | public @interface MarkupInclude { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/append/JsonDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.append; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.lang.reflect.Type; 6 | import java.nio.file.Files; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import com.aventstack.extentreports.model.Media; 11 | import com.aventstack.extentreports.model.Test; 12 | import com.google.gson.Gson; 13 | import com.google.gson.GsonBuilder; 14 | import com.google.gson.reflect.TypeToken; 15 | 16 | public class JsonDeserializer { 17 | private File f; 18 | 19 | public JsonDeserializer(File f) { 20 | this.f = f; 21 | } 22 | 23 | public List deserialize() throws IOException { 24 | Gson gson = new GsonBuilder() 25 | .registerTypeAdapter(Media.class, new ScreenCaptureTypeAdapter()) 26 | .create(); 27 | String json = new String(Files.readAllBytes(f.toPath())); 28 | Type t = new TypeToken>() { 29 | }.getType(); 30 | List tests = gson.fromJson(json, t); 31 | return tests; 32 | } 33 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/append/ScreenCaptureTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.append; 2 | 3 | import java.io.IOException; 4 | 5 | import com.aventstack.extentreports.model.Media; 6 | import com.aventstack.extentreports.model.ScreenCapture; 7 | import com.google.gson.TypeAdapter; 8 | import com.google.gson.stream.JsonReader; 9 | import com.google.gson.stream.JsonToken; 10 | import com.google.gson.stream.JsonWriter; 11 | 12 | public class ScreenCaptureTypeAdapter extends TypeAdapter { 13 | 14 | @Override 15 | public void write(JsonWriter out, Media value) throws IOException { 16 | } 17 | 18 | @Override 19 | public Media read(JsonReader reader) throws IOException { 20 | ScreenCapture sc = ScreenCapture.builder().build(); 21 | reader.beginObject(); 22 | String fieldName = null; 23 | int cycle = 0; 24 | while (reader.hasNext()) { 25 | JsonToken token = reader.peek(); 26 | if (token.equals(JsonToken.NAME)) { 27 | fieldName = reader.nextName(); 28 | } 29 | if ("string".equalsIgnoreCase(token.name()) && fieldName.equalsIgnoreCase("path")) { 30 | token = reader.peek(); 31 | sc.setPath(reader.nextString()); 32 | } 33 | if ("string".equalsIgnoreCase(token.name()) && fieldName.equalsIgnoreCase("resolvedPath")) { 34 | token = reader.peek(); 35 | sc.setResolvedPath(reader.nextString()); 36 | } 37 | if ("string".equalsIgnoreCase(token.name()) && fieldName.equalsIgnoreCase("base64")) { 38 | token = reader.peek(); 39 | sc.setBase64(reader.nextString()); 40 | } 41 | if (cycle++ > 10) 42 | return sc; 43 | } 44 | reader.endObject(); 45 | return sc; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/config/ConfigStore.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.config; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | @Getter 10 | @Setter 11 | public class ConfigStore { 12 | private Map store = new HashMap(); 13 | 14 | public void addConfig(String key, Object value) { 15 | store.put(key, value); 16 | } 17 | 18 | public boolean containsConfig(String k) { 19 | return store.containsKey(k); 20 | } 21 | 22 | public void removeConfig(String k) { 23 | store.remove(k); 24 | } 25 | 26 | public Object getConfig(String k) { 27 | return store.get(k); 28 | } 29 | 30 | public void extendConfig(Map map) { 31 | map.forEach((key, value) -> this.addConfig(key, value)); 32 | } 33 | 34 | public void extendConfig(ConfigStore configMap) { 35 | this.extendConfig(configMap.getStore()); 36 | } 37 | 38 | public boolean isEmpty() { 39 | return store.isEmpty(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/config/external/CaseInsensitiveEnumTypeAdapterFactory.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.config.external; 2 | 3 | import java.io.IOException; 4 | import java.util.HashMap; 5 | import java.util.Locale; 6 | import java.util.Map; 7 | 8 | import com.google.gson.Gson; 9 | import com.google.gson.TypeAdapter; 10 | import com.google.gson.TypeAdapterFactory; 11 | import com.google.gson.reflect.TypeToken; 12 | import com.google.gson.stream.JsonReader; 13 | import com.google.gson.stream.JsonToken; 14 | import com.google.gson.stream.JsonWriter; 15 | 16 | public class CaseInsensitiveEnumTypeAdapterFactory implements TypeAdapterFactory { 17 | @SuppressWarnings("unchecked") 18 | public TypeAdapter create(Gson gson, TypeToken type) { 19 | Class rawType = (Class) type.getRawType(); 20 | if (!rawType.isEnum()) { 21 | return null; 22 | } 23 | 24 | final Map lowercaseToConstant = new HashMap(); 25 | for (T constant : rawType.getEnumConstants()) { 26 | lowercaseToConstant.put(toLowercase(constant), constant); 27 | } 28 | 29 | return new TypeAdapter() { 30 | public void write(JsonWriter out, T value) throws IOException { 31 | if (value == null) { 32 | out.nullValue(); 33 | } else { 34 | out.value(toLowercase(value)); 35 | } 36 | } 37 | 38 | public T read(JsonReader reader) throws IOException { 39 | if (reader.peek() == JsonToken.NULL) { 40 | reader.nextNull(); 41 | return null; 42 | } else { 43 | return lowercaseToConstant.get(toLowercase(reader.nextString())); 44 | } 45 | } 46 | }; 47 | } 48 | 49 | private String toLowercase(Object o) { 50 | return o.toString().toLowerCase(Locale.US); 51 | } 52 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/config/external/ConfigLoadable.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.config.external; 2 | 3 | @FunctionalInterface 4 | public interface ConfigLoadable { 5 | void apply(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/config/external/JsonConfigLoader.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.config.external; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.lang.reflect.Type; 7 | 8 | import org.testng.reporters.Files; 9 | 10 | import com.google.gson.Gson; 11 | import com.google.gson.GsonBuilder; 12 | import com.google.gson.InstanceCreator; 13 | 14 | public class JsonConfigLoader implements ConfigLoadable { 15 | private File f; 16 | private String json; 17 | private T instance; 18 | private InstanceCreator creator; 19 | 20 | public JsonConfigLoader(T instance, File f) throws FileNotFoundException { 21 | if (f == null) 22 | throw new IllegalArgumentException("File cannot be null"); 23 | if (!f.exists()) 24 | throw new FileNotFoundException("File " + f.getAbsolutePath() + " could not be found"); 25 | init(instance); 26 | this.f = f; 27 | } 28 | 29 | public JsonConfigLoader(T instance, String json) { 30 | if (json == null || json.isEmpty()) 31 | throw new IllegalArgumentException("Json input cannot be null or empty"); 32 | init(instance); 33 | this.json = json; 34 | } 35 | 36 | private void init(T instance) { 37 | this.instance = instance; 38 | creator = new InstanceCreator() { 39 | @Override 40 | public T createInstance(Type type) { 41 | return instance; 42 | } 43 | }; 44 | } 45 | 46 | @SuppressWarnings("unchecked") 47 | public void apply() { 48 | final Gson gson = new GsonBuilder() 49 | .registerTypeAdapter(instance.getClass(), creator) 50 | .create(); 51 | try { 52 | String json = f != null ? Files.readFile(f) : this.json; 53 | instance = (T) gson.fromJson(json, instance.getClass()); 54 | } catch (IOException e) { 55 | e.printStackTrace(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/GherkinDialect.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | 9 | /** 10 | *

11 | * Modified version of GherkinKeyword.java from cucumber/gherkin. Source url: 12 | * https://raw.githubusercontent.com/cucumber/cucumber/master/gherkin/java/src/main/java/gherkin/GherkinDialect.java 13 | * 14 | *

15 | * Gherkin source is licensed under the MIT License 16 | * 17 | */ 18 | @Getter 19 | @ToString 20 | public class GherkinDialect { 21 | private final Map> keywords; 22 | private String language; 23 | 24 | public GherkinDialect(String language, Map> keywords) { 25 | keywords.remove("name"); 26 | keywords.remove("native"); 27 | this.language = language; 28 | this.keywords = keywords; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/model/And.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin.model; 2 | 3 | import java.io.Serializable; 4 | 5 | public class And implements IGherkinFormatterModel, Serializable { 6 | private static final long serialVersionUID = 8543289653944756660L; 7 | private static final String VALUE = "And"; 8 | 9 | public static String getGherkinName() { 10 | return VALUE; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return getGherkinName(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/model/Asterisk.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin.model; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Asterisk implements IGherkinFormatterModel, Serializable { 6 | private static final long serialVersionUID = 7251419811428200133L; 7 | private static final String VALUE = "*"; 8 | 9 | public static String getGherkinName() { 10 | return VALUE; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return getGherkinName(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/model/Background.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin.model; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Background implements IGherkinFormatterModel, Serializable { 6 | private static final long serialVersionUID = -955371501488725151L; 7 | private static final String VALUE = "Background"; 8 | 9 | public static String getGherkinName() { 10 | return VALUE; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return getGherkinName(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/model/But.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin.model; 2 | 3 | import java.io.Serializable; 4 | 5 | public class But implements IGherkinFormatterModel, Serializable { 6 | private static final long serialVersionUID = 3420514631996827220L; 7 | private static final String VALUE = "But"; 8 | 9 | public static String getGherkinName() { 10 | return VALUE; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return getGherkinName(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/model/Feature.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin.model; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Feature implements IGherkinFormatterModel, Serializable { 6 | private static final long serialVersionUID = -4719215211721789414L; 7 | private static final String VALUE = "Feature"; 8 | 9 | public static String getGherkinName() { 10 | return VALUE; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return getGherkinName(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/model/GherkinEntity.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin.model; 2 | 3 | import java.io.Serializable; 4 | 5 | public abstract class GherkinEntity implements Serializable { 6 | private static final long serialVersionUID = 725203884274843593L; 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/model/Given.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin.model; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Given implements IGherkinFormatterModel, Serializable { 6 | private static final long serialVersionUID = 939197985263690070L; 7 | private static final String VALUE = "Given"; 8 | 9 | public static String getGherkinName() { 10 | return VALUE; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return getGherkinName(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/model/IGherkinFormatterModel.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin.model; 2 | 3 | import java.io.Serializable; 4 | 5 | public interface IGherkinFormatterModel extends Serializable { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/model/Scenario.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin.model; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Scenario implements IGherkinFormatterModel, Serializable { 6 | private static final long serialVersionUID = 7401124129196617280L; 7 | private static final String VALUE = "Scenario"; 8 | 9 | public static String getGherkinName() { 10 | return VALUE; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return getGherkinName(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/model/ScenarioOutline.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin.model; 2 | 3 | import java.io.Serializable; 4 | 5 | public class ScenarioOutline implements IGherkinFormatterModel, Serializable { 6 | private static final long serialVersionUID = -2058398543903906031L; 7 | private static final String VALUE = "Scenario Outline"; 8 | 9 | public static String getGherkinName() { 10 | return VALUE; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return getGherkinName(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/model/Then.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin.model; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Then implements IGherkinFormatterModel, Serializable { 6 | private static final long serialVersionUID = 2493591502473169772L; 7 | private static final String VALUE = "Then"; 8 | 9 | public static String getGherkinName() { 10 | return VALUE; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return getGherkinName(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/gherkin/model/When.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.gherkin.model; 2 | 3 | import java.io.Serializable; 4 | 5 | public class When implements IGherkinFormatterModel, Serializable { 6 | private static final long serialVersionUID = 8337259741948416898L; 7 | private static final String VALUE = "When"; 8 | 9 | public static String getGherkinName() { 10 | return VALUE; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return getGherkinName(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/io/BufferedWriterWriter.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.io; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileWriter; 6 | import java.util.logging.Level; 7 | import java.util.logging.Logger; 8 | 9 | public class BufferedWriterWriter { 10 | 11 | private static class WriterInstance { 12 | static final BufferedWriterWriter INSTANCE = new BufferedWriterWriter(); 13 | 14 | private WriterInstance() { 15 | } 16 | } 17 | 18 | static final Logger logger = Logger.getLogger(BufferedWriterWriter.class.getName()); 19 | 20 | private BufferedWriterWriter() { 21 | } 22 | 23 | public synchronized void write(final File f, String text) { 24 | try (BufferedWriter writer = new BufferedWriter(new FileWriter(f))) { 25 | writer.write(text); 26 | } catch (Exception e) { 27 | logger.log(Level.SEVERE, f.getPath(), e); 28 | } 29 | } 30 | 31 | public static BufferedWriterWriter getInstance() { 32 | return WriterInstance.INSTANCE; 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/markuputils/CodeBlock.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | import java.io.IOException; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | import com.google.gson.Gson; 9 | 10 | import freemarker.template.Template; 11 | import freemarker.template.TemplateException; 12 | import lombok.AllArgsConstructor; 13 | import lombok.Builder; 14 | import lombok.Getter; 15 | import lombok.ToString; 16 | 17 | @Getter 18 | @Builder 19 | @AllArgsConstructor 20 | @ToString 21 | class CodeBlock extends MarkupTemplate implements Markup { 22 | 23 | private static final long serialVersionUID = -5532095355983830164L; 24 | private static final AtomicInteger id = new AtomicInteger(0); 25 | private static final String CODEBLOCK_TEMPLATE = "codeblock.ftl"; 26 | private static final String CODEBLOCK_JSON_TEMPLATE = "codeblock.json.ftl"; 27 | private static Template codeblock; 28 | private static Template codeblockJson; 29 | private String code; 30 | private CodeLanguage lang; 31 | private Object jsonObject; 32 | 33 | static { 34 | try { 35 | codeblock = ft.createTemplate(CODEBLOCK_TEMPLATE); 36 | codeblockJson = ft.createTemplate(CODEBLOCK_JSON_TEMPLATE); 37 | } catch (Exception e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | 42 | @Override 43 | public String getMarkup() { 44 | if (code == null && jsonObject == null) 45 | return ""; 46 | if (jsonObject != null) 47 | code = new Gson().toJson(jsonObject); 48 | int index = 0; 49 | Template t = codeblock; 50 | if (lang == CodeLanguage.JSON) { 51 | index = id.getAndIncrement(); 52 | t = codeblockJson; 53 | } 54 | Map map = new HashMap<>(); 55 | map.put("code", code); 56 | map.put("index", index); 57 | try { 58 | return ft.getSource(t, map); 59 | } catch (TemplateException e) { 60 | e.printStackTrace(); 61 | } catch (IOException e) { 62 | e.printStackTrace(); 63 | } 64 | return null; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/markuputils/CodeLanguage.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | /** 4 | * List of supported languages that will be prettified on output 5 | */ 6 | public enum CodeLanguage { 7 | XML, JSON 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/markuputils/ExtentColor.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | public enum ExtentColor { 4 | RED, 5 | PINK, 6 | PURPLE, 7 | INDIGO, 8 | BLUE, 9 | CYAN, 10 | TEAL, 11 | GREEN, 12 | LIME, 13 | YELLOW, 14 | AMBER, 15 | ORANGE, 16 | BROWN, 17 | GREY, 18 | WHITE, 19 | BLACK, 20 | TRANSPARENT 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/markuputils/HtmlList.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.Set; 8 | 9 | abstract class HtmlList { 10 | @SuppressWarnings("unchecked") 11 | protected String getList(Object object, ListType listType) { 12 | final StringBuilder sb = new StringBuilder(); 13 | sb.append("<" + listType.toString().toLowerCase() + ">"); 14 | if (object instanceof Map) { 15 | for (Map.Entry entry : ((Map) object).entrySet()) { 16 | sb.append("

  • "); 17 | sb.append(entry.getKey()); 18 | sb.append(":"); 19 | sb.append(entry.getValue()); 20 | sb.append("
  • "); 21 | } 22 | } else if (object instanceof List || object instanceof Set || object.getClass().isArray()) { 23 | if (object.getClass().isArray()) 24 | object = Arrays.asList((Object[])object); 25 | for (Object o : (Collection) object) { 26 | sb.append("
  • "); 27 | sb.append(o.toString()); 28 | sb.append("
  • "); 29 | } 30 | } else { 31 | sb.append("
  • "); 32 | sb.append(object.toString()); 33 | sb.append("
  • "); 34 | } 35 | sb.append(""); 36 | return sb.toString(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/markuputils/Label.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | @Getter 10 | @Setter 11 | @Builder 12 | @AllArgsConstructor 13 | @ToString 14 | class Label implements Markup { 15 | private static final long serialVersionUID = 548763908072445261L; 16 | 17 | private String text; 18 | private ExtentColor color; 19 | 20 | public String getMarkup() { 21 | if (text == null || text.isEmpty()) 22 | return ""; 23 | String textColor = color != ExtentColor.WHITE ? "white-text" : "black-text"; 24 | String lhs = ""; 25 | String rhs = ""; 26 | return lhs + text + rhs; 27 | } 28 | 29 | public static class LabelBuilder { 30 | private String text = ""; 31 | private ExtentColor color = ExtentColor.TRANSPARENT; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/markuputils/ListType.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | enum ListType { 4 | OL, UL 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/markuputils/Markup.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | import java.io.Serializable; 4 | 5 | @FunctionalInterface 6 | public interface Markup extends Serializable { 7 | String getMarkup(); 8 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/markuputils/MarkupHelper.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | public class MarkupHelper { 4 | 5 | public static Markup createLabel(String text, ExtentColor color) { 6 | return Label.builder().text(text).color(color).build(); 7 | } 8 | 9 | public static Markup createCodeBlock(String code) { 10 | return CodeBlock.builder().code(code).build(); 11 | } 12 | 13 | public static Markup createCodeBlock(String code, CodeLanguage lang) { 14 | return CodeBlock.builder().code(code).lang(lang).build(); 15 | } 16 | 17 | public static Markup createCodeBlock(Object o) { 18 | return CodeBlock.builder().jsonObject(o).lang(CodeLanguage.JSON).build(); 19 | } 20 | 21 | /** 22 | * Creates an ordered list from one of the following underlying collections 23 | * 24 | *
      25 | *
    • List
    • 26 | *
    • Map
    • 27 | *
    • Set
    • 28 | *
    29 | * 30 | * @param o 31 | * An iterable collection 32 | * @return {@link Markup} 33 | */ 34 | public static Markup createOrderedList(Object o) { 35 | return OrderedList.builder().object(o).build(); 36 | } 37 | 38 | /** 39 | * Creates an unordered list from one of the following underlying 40 | * collections 41 | * 42 | *
      43 | *
    • List
    • 44 | *
    • Map
    • 45 | *
    • Set
    • 46 | *
    47 | * 48 | * @param o 49 | * An iterable collection 50 | * @return {@link Markup} 51 | */ 52 | public static Markup createUnorderedList(Object o) { 53 | return UnorderedList.builder().object(o).build(); 54 | } 55 | 56 | public static Markup createTable(String[][] data, String[] cssClass) { 57 | return Table.builder().data(data).cssClasses(cssClass).build(); 58 | } 59 | 60 | public static Markup createTable(String[][] data, String cssClass) { 61 | return Table.builder().data(data).cssClass(cssClass).build(); 62 | } 63 | 64 | public static Markup createTable(String[][] data) { 65 | return Table.builder().data(data).build(); 66 | } 67 | 68 | public static Markup toTable(Object o, String[] cssClass) { 69 | return Table.builder().object(o).cssClasses(cssClass).build(); 70 | } 71 | 72 | public static Markup toTable(Object o, String cssClass) { 73 | return Table.builder().object(o).cssClass(cssClass).build(); 74 | } 75 | 76 | public static Markup toTable(Object o) { 77 | return Table.builder().object(o).build(); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/markuputils/MarkupTemplate.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | import com.aventstack.extentreports.ExtentReports; 4 | import com.aventstack.extentreports.templating.FreemarkerTemplate; 5 | 6 | class MarkupTemplate { 7 | protected static final FreemarkerTemplate ft = new FreemarkerTemplate(ExtentReports.class, "markup/", "UTF-8"); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/markuputils/OrderedList.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | import lombok.ToString; 7 | 8 | @Getter 9 | @Builder 10 | @AllArgsConstructor 11 | @ToString 12 | public class OrderedList extends HtmlList implements Markup { 13 | private static final long serialVersionUID = -1763712576872406878L; 14 | 15 | private Object object; 16 | 17 | @Override 18 | public String getMarkup() { 19 | return getList(object, ListType.OL); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/markuputils/UnorderedList.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | import lombok.ToString; 7 | 8 | @Getter 9 | @Builder 10 | @AllArgsConstructor 11 | @ToString 12 | class UnorderedList extends HtmlList implements Markup { 13 | private static final long serialVersionUID = 2056301782889894819L; 14 | 15 | private Object object; 16 | 17 | @Override 18 | public String getMarkup() { 19 | return getList(object, ListType.UL); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/markuputils/util/ReflectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils.util; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.lang.reflect.Field; 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.Collections; 8 | import java.util.List; 9 | import java.util.stream.Collectors; 10 | 11 | public class ReflectionUtil { 12 | public static List getFieldsIgnoringAnnotation(Class clazz, 13 | Class skippingAnnotationClazz) { 14 | if (clazz == null) 15 | return Collections.emptyList(); 16 | List fields = new ArrayList<>( 17 | getFieldsIgnoringAnnotation(clazz.getSuperclass(), skippingAnnotationClazz)); 18 | List filteredList = Arrays.stream(clazz.getDeclaredFields()) 19 | .filter(x -> !x.isAnnotationPresent(skippingAnnotationClazz)) 20 | .collect(Collectors.toList()); 21 | fields.addAll(filteredList); 22 | return fields; 23 | } 24 | 25 | public static List getAnnotatedFields(Class clazz, 26 | Class annotationClazz) { 27 | if (clazz == null) 28 | return Collections.emptyList(); 29 | List fields = new ArrayList<>(getAnnotatedFields(clazz.getSuperclass(), annotationClazz)); 30 | List filteredList = Arrays.stream(clazz.getDeclaredFields()) 31 | .filter(x -> x.isAnnotationPresent(annotationClazz)) 32 | .collect(Collectors.toList()); 33 | fields.addAll(filteredList); 34 | return fields; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/Author.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | @Getter 10 | @Setter 11 | @ToString(callSuper = true, includeFieldNames = true) 12 | public final class Author extends NamedAttribute implements Serializable, BaseEntity { 13 | private static final long serialVersionUID = -1589597649718748057L; 14 | 15 | public Author(String name) { 16 | super(name); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | /** 4 | * Marker interface for entities 5 | */ 6 | public interface BaseEntity { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/Category.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | @Getter 10 | @Setter 11 | @ToString(callSuper = true, includeFieldNames = true) 12 | public final class Category extends NamedAttribute implements Serializable, BaseEntity { 13 | private static final long serialVersionUID = 5282727628859917993L; 14 | 15 | public Category(String name) { 16 | super(name); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/Device.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | @Getter 10 | @Setter 11 | @ToString(callSuper = true, includeFieldNames = true) 12 | public final class Device extends NamedAttribute implements Serializable { 13 | private static final long serialVersionUID = -5585746447313067401L; 14 | 15 | public Device(String name) { 16 | super(name); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/ExceptionInfo.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import lombok.ToString; 9 | 10 | @Getter 11 | @Setter 12 | @ToString 13 | public class ExceptionInfo extends NamedAttribute implements Serializable, BaseEntity { 14 | private static final long serialVersionUID = -8152865623044194249L; 15 | private Throwable exception; 16 | private String stackTrace; 17 | 18 | @Builder 19 | public ExceptionInfo(Throwable exception, String name, String stackTrace) { 20 | super(name); 21 | this.exception = exception; 22 | this.stackTrace = stackTrace; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/Log.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | import java.io.Serializable; 4 | import java.util.Calendar; 5 | import java.util.Date; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import com.aventstack.extentreports.Status; 10 | 11 | import lombok.AllArgsConstructor; 12 | import lombok.Builder; 13 | import lombok.Getter; 14 | import lombok.NoArgsConstructor; 15 | import lombok.Setter; 16 | import lombok.ToString; 17 | 18 | @Getter 19 | @Setter 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | @Builder 23 | @ToString 24 | public class Log implements RunResult, Serializable, BaseEntity { 25 | private static final long serialVersionUID = -3690764012141784427L; 26 | 27 | @Builder.Default 28 | private Date timestamp = Calendar.getInstance().getTime(); 29 | @Builder.Default 30 | private Status status = Status.PASS; 31 | private String details; 32 | @Builder.Default 33 | private Integer seq = -1; 34 | private final Map infoMap = new HashMap<>(); 35 | private Media media; 36 | private ExceptionInfo exception; 37 | 38 | public final boolean hasException() { 39 | return exception != null; 40 | } 41 | 42 | public final void addMedia(Media media) { 43 | if (media != null && ((media.getPath() != null || media.getResolvedPath() != null) 44 | || media instanceof ScreenCapture && ((ScreenCapture) media).getBase64() != null)) 45 | this.media = media; 46 | } 47 | 48 | public final boolean hasMedia() { 49 | return media != null; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/Media.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | @Getter 10 | @Setter 11 | @AllArgsConstructor 12 | public class Media implements Serializable, BaseEntity { 13 | private static final long serialVersionUID = 5428859443090457608L; 14 | 15 | private String path; 16 | private String title; 17 | private String resolvedPath; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/NameValuePair.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | public abstract class NameValuePair extends NamedAttribute implements Serializable, BaseEntity { 11 | private static final long serialVersionUID = 6613712676810614719L; 12 | private String value; 13 | 14 | public NameValuePair(String name, String value) { 15 | super(name); 16 | this.value = value; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/NamedAttribute.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import lombok.AllArgsConstructor; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import lombok.experimental.SuperBuilder; 10 | 11 | @Getter 12 | @Setter 13 | @SuperBuilder 14 | @AllArgsConstructor 15 | @EqualsAndHashCode 16 | public abstract class NamedAttribute implements Serializable, BaseEntity { 17 | private static final long serialVersionUID = -804568330360505098L; 18 | private String name; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/Report.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.Calendar; 6 | import java.util.Collections; 7 | import java.util.Date; 8 | import java.util.List; 9 | import java.util.stream.Collectors; 10 | 11 | import com.aventstack.extentreports.Status; 12 | import com.aventstack.extentreports.model.context.NamedAttributeContextManager; 13 | 14 | import lombok.AllArgsConstructor; 15 | import lombok.Builder; 16 | import lombok.Getter; 17 | import lombok.Setter; 18 | import lombok.ToString; 19 | 20 | @Getter 21 | @Setter 22 | @AllArgsConstructor 23 | @Builder 24 | @ToString(includeFieldNames = true) 25 | public class Report implements Serializable, BaseEntity { 26 | private static final long serialVersionUID = -8667496631392333349L; 27 | 28 | @Builder.Default 29 | private Date startTime = Calendar.getInstance().getTime(); 30 | @Builder.Default 31 | private Date endTime = Calendar.getInstance().getTime(); 32 | @Builder.Default 33 | private Status status = Status.PASS; 34 | private final transient ReportStats stats = new ReportStats(); 35 | private final List testList = Collections.synchronizedList(new ArrayList<>()); 36 | private final transient NamedAttributeContextManager authorCtx = new NamedAttributeContextManager<>(); 37 | private final transient NamedAttributeContextManager categoryCtx = new NamedAttributeContextManager<>(); 38 | private final transient NamedAttributeContextManager deviceCtx = new NamedAttributeContextManager<>(); 39 | private final transient NamedAttributeContextManager exceptionInfoCtx = new NamedAttributeContextManager<>(); 40 | private final List logs = Collections.synchronizedList(new ArrayList<>()); 41 | private final List systemEnvInfo = new ArrayList<>(); 42 | 43 | public final boolean isBDD() { 44 | return !testList.isEmpty() && testList.stream().allMatch(Test::isBDD); 45 | } 46 | 47 | public final boolean anyTestHasStatus(Status status) { 48 | return testList.stream() 49 | .anyMatch(x -> x.getStatus() == status); 50 | } 51 | 52 | public final long timeTaken() { 53 | return endTime.getTime() - startTime.getTime(); 54 | } 55 | 56 | public final Status getStatus() { 57 | List list = testList 58 | .stream() 59 | .map(x -> x.getStatus()) 60 | .collect(Collectors.toList()); 61 | return Status.max(list); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/RunResult.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | import com.aventstack.extentreports.Status; 4 | 5 | @FunctionalInterface 6 | public interface RunResult { 7 | Status getStatus(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/ScreenCapture.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | @Getter 10 | @Setter 11 | public class ScreenCapture extends Media implements Serializable { 12 | private static final long serialVersionUID = -3047762572007885369L; 13 | 14 | private String base64; 15 | 16 | @Builder 17 | public ScreenCapture(String path, String title, String resolvedPath, String base64) { 18 | super(path, title, resolvedPath); 19 | this.base64 = base64; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/SystemEnvInfo.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | @Getter 10 | @Setter 11 | @ToString(callSuper = true, includeFieldNames = true) 12 | public class SystemEnvInfo extends NameValuePair implements Serializable, BaseEntity { 13 | private static final long serialVersionUID = 8643409194315531097L; 14 | 15 | public SystemEnvInfo(String name, String value) { 16 | super(name, value); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/context/NamedAttributeContext.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model.context; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | import com.aventstack.extentreports.Status; 9 | import com.aventstack.extentreports.model.NamedAttribute; 10 | import com.aventstack.extentreports.model.Test; 11 | 12 | import lombok.Getter; 13 | import lombok.ToString; 14 | 15 | @Getter 16 | @ToString 17 | public class NamedAttributeContext implements Serializable { 18 | private static final long serialVersionUID = -2671203343283101908L; 19 | 20 | private final List testList = Collections.synchronizedList(new ArrayList<>()); 21 | private T attr; 22 | private Integer passed = 0; 23 | private Integer failed = 0; 24 | private Integer skipped = 0; 25 | private Integer others = 0; 26 | 27 | public NamedAttributeContext(T attribute, Test test) { 28 | this.attr = attribute; 29 | addTest(test); 30 | } 31 | 32 | public void addTest(Test test) { 33 | if (test == null) 34 | throw new IllegalArgumentException("Test cannot be null"); 35 | testList.add(test); 36 | refresh(test); 37 | } 38 | 39 | private synchronized void refresh(Test test) { 40 | if (test.getStatus() == Status.PASS) 41 | passed++; 42 | else if (test.getStatus() == Status.FAIL) 43 | failed++; 44 | else if (test.getStatus() == Status.SKIP) 45 | skipped++; 46 | else 47 | others++; 48 | } 49 | 50 | public void refresh() { 51 | passed = failed = skipped = others = 0; 52 | testList.forEach(this::refresh); 53 | } 54 | 55 | public Integer size() { 56 | return passed + failed + skipped + others; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/context/NamedAttributeContextManager.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model.context; 2 | 3 | import java.util.Collections; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.Set; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | import com.aventstack.extentreports.model.NamedAttribute; 11 | import com.aventstack.extentreports.model.Test; 12 | import com.aventstack.extentreports.model.service.TestService; 13 | 14 | import lombok.Getter; 15 | import lombok.NoArgsConstructor; 16 | 17 | @NoArgsConstructor 18 | @Getter 19 | public class NamedAttributeContextManager { 20 | private Set> set = Collections 21 | .newSetFromMap(new ConcurrentHashMap, Boolean>()); 22 | 23 | public void addContext(T attr, Test test) { 24 | Optional> opt = set.stream() 25 | .filter(x -> x.getAttr().getName().equals(attr.getName())) 26 | .findAny(); 27 | if (opt.isPresent()) { 28 | List list = opt.get().getTestList(); 29 | if (!list.stream().anyMatch(t -> t.getId() == test.getId())) 30 | list.add(test); 31 | } else { 32 | set.add(new NamedAttributeContext<>(attr, test)); 33 | } 34 | } 35 | 36 | public void addContext(T attr, List testList) { 37 | testList.forEach(x -> addContext(attr, x)); 38 | } 39 | 40 | /** 41 | * Remove a test from the context. This will also removed the context if 42 | * there are no tests present after test removal 43 | * 44 | * @param test 45 | * {@link Test} 46 | */ 47 | public void removeTest(Test test) { 48 | Iterator> iter = set.iterator(); 49 | while (iter.hasNext()) { 50 | NamedAttributeContext context = iter.next(); 51 | TestService.deleteTest(context.getTestList(), test); 52 | if (context.getTestList().isEmpty()) 53 | iter.remove(); 54 | } 55 | } 56 | 57 | public boolean hasItems() { 58 | return !set.isEmpty(); 59 | } 60 | 61 | public void resetAll() { 62 | set.stream().forEach(x -> x.refresh()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/context/filter/NamedAttributeTestContextFilter.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model.context.filter; 2 | 3 | import java.util.List; 4 | import java.util.Set; 5 | import java.util.stream.Collectors; 6 | 7 | import com.aventstack.extentreports.Status; 8 | import com.aventstack.extentreports.model.NamedAttribute; 9 | import com.aventstack.extentreports.model.Test; 10 | import com.aventstack.extentreports.model.context.NamedAttributeContextManager; 11 | import com.aventstack.extentreports.model.context.NamedAttributeContext; 12 | 13 | public class NamedAttributeTestContextFilter { 14 | public Set> filter(NamedAttributeContextManager mgr, Set status) { 15 | NamedAttributeContextManager newmgr = new NamedAttributeContextManager(); 16 | mgr.getSet().stream() 17 | .forEach(x -> newmgr.addContext(x.getAttr(), x.getTestList())); 18 | List unwantedList = newmgr.getSet().stream() 19 | .flatMap(x -> x.getTestList().stream()) 20 | .filter(x -> !status.contains(x.getStatus())) 21 | .collect(Collectors.toList()); 22 | unwantedList.forEach(newmgr::removeTest); 23 | return newmgr.getSet(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/service/EntityService.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model.service; 2 | 3 | public interface EntityService { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/service/ExceptionInfoService.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model.service; 2 | 3 | import com.aventstack.extentreports.model.ExceptionInfo; 4 | import com.aventstack.extentreports.model.service.util.ExceptionUtil; 5 | 6 | public class ExceptionInfoService { 7 | public static ExceptionInfo createExceptionInfo(Throwable t) { 8 | if (t == null) 9 | return null; 10 | ExceptionInfo exceptionInfo = ExceptionInfo.builder() 11 | .exception(t) 12 | .name(ExceptionUtil.getExceptionHeadline(t)) 13 | .stackTrace(ExceptionUtil.getStackTrace(t)) 14 | .build(); 15 | return exceptionInfo; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/service/MediaService.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model.service; 2 | 3 | import java.io.File; 4 | import java.nio.file.Path; 5 | import java.nio.file.Paths; 6 | 7 | import com.aventstack.extentreports.model.Media; 8 | import com.aventstack.extentreports.model.ScreenCapture; 9 | 10 | public class MediaService { 11 | public static void tryResolveMediaPath(Media media, String[] knownPath) { 12 | if (knownPath == null || (media instanceof ScreenCapture && ((ScreenCapture) media).getBase64() != null)) 13 | return; 14 | String loc = media.getPath(); 15 | File f = new File(loc); 16 | if (!new File(loc).exists()) { 17 | for (String p : knownPath) { 18 | Path path = Paths.get(p, loc); 19 | if (path.toFile().exists()) { 20 | media.setResolvedPath(path.toFile().getAbsolutePath()); 21 | break; 22 | } 23 | path = Paths.get(p, f.getName()); 24 | if (path.toFile().exists()) { 25 | media.setResolvedPath(path.toFile().getAbsolutePath()); 26 | break; 27 | } 28 | } 29 | } 30 | } 31 | 32 | public static boolean isBase64(Media m) { 33 | return m instanceof ScreenCapture && ((ScreenCapture) m).getBase64() != null; 34 | } 35 | 36 | public static String getBase64(Media m) { 37 | if (isBase64(m)) 38 | return ((ScreenCapture) m).getBase64(); 39 | return null; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/service/ReportFilterService.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model.service; 2 | 3 | import java.util.List; 4 | import java.util.Set; 5 | import java.util.stream.Collectors; 6 | 7 | import com.aventstack.extentreports.Status; 8 | import com.aventstack.extentreports.model.Author; 9 | import com.aventstack.extentreports.model.Category; 10 | import com.aventstack.extentreports.model.Device; 11 | import com.aventstack.extentreports.model.Report; 12 | import com.aventstack.extentreports.model.Test; 13 | import com.aventstack.extentreports.model.context.NamedAttributeContext; 14 | import com.aventstack.extentreports.model.context.filter.NamedAttributeTestContextFilter; 15 | 16 | public class ReportFilterService { 17 | public static Report filter(Report report, Set statusList) { 18 | if (report.getTestList().isEmpty()) 19 | return report; 20 | Report filtered = Report.builder().build(); 21 | filtered.getLogs().addAll(report.getLogs()); 22 | filtered.setStartTime(report.getStartTime()); 23 | filtered.setEndTime(report.getEndTime()); 24 | List list = report.getTestList().stream() 25 | .filter(x -> statusList.contains(x.getStatus())) 26 | .collect(Collectors.toList()); 27 | list.forEach(filtered.getTestList()::add); 28 | filtered.getStats().update(list); 29 | Set> authorCtx = new NamedAttributeTestContextFilter() 30 | .filter(report.getAuthorCtx(), statusList); 31 | authorCtx.stream().forEach(x -> filtered.getAuthorCtx().addContext(x.getAttr(), x.getTestList())); 32 | Set> categoryCtx = new NamedAttributeTestContextFilter() 33 | .filter(report.getCategoryCtx(), statusList); 34 | categoryCtx.stream().forEach(x -> filtered.getCategoryCtx().addContext(x.getAttr(), x.getTestList())); 35 | Set> deviceCtx = new NamedAttributeTestContextFilter() 36 | .filter(report.getDeviceCtx(), statusList); 37 | deviceCtx.stream().forEach(x -> filtered.getDeviceCtx().addContext(x.getAttr(), x.getTestList())); 38 | return filtered; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/service/TestService.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model.service; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Calendar; 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.stream.Collectors; 8 | 9 | import com.aventstack.extentreports.gherkin.model.IGherkinFormatterModel; 10 | import com.aventstack.extentreports.model.ExceptionInfo; 11 | import com.aventstack.extentreports.model.Log; 12 | import com.aventstack.extentreports.model.Test; 13 | 14 | public class TestService { 15 | public static boolean deleteTest(List list, Test test) { 16 | boolean removed = list.removeIf(x -> x.getId() == test.getId()); 17 | if (!removed) 18 | list.forEach(x -> deleteTest(x.getChildren(), test)); 19 | return removed; 20 | } 21 | 22 | public static Optional findTest(List list, String name) { 23 | Optional test = list.stream().filter(x -> x.getName().equals(name)).findFirst(); 24 | if (!test.isPresent()) 25 | for (Test t : list) 26 | return findTest(t.getChildren(), name); 27 | return test; 28 | } 29 | 30 | public static Boolean testHasScreenCapture(Test test, Boolean deep) { 31 | if (deep) { 32 | Boolean hasScreenCapture = !test.getMedia().isEmpty() 33 | || test.getLogs().stream().anyMatch(Log::hasMedia); 34 | if (!hasScreenCapture) 35 | hasScreenCapture = test.getChildren().stream().anyMatch(x -> testHasScreenCapture(x, deep)); 36 | return hasScreenCapture; 37 | } 38 | return test.hasScreenCapture(); 39 | } 40 | 41 | public static List aggregateExceptions(List testList) { 42 | List list = new ArrayList<>(); 43 | for (Test test : testList) { 44 | list.addAll(aggregateExceptions(test)); 45 | if (!test.getChildren().isEmpty()) 46 | aggregateExceptions(test.getChildren()); 47 | } 48 | return list; 49 | } 50 | 51 | public static List aggregateExceptions(Test test) { 52 | return test.getLogs().stream() 53 | .filter(x -> x.getException() != null) 54 | .map(x -> x.getException()) 55 | .collect(Collectors.toList()); 56 | } 57 | 58 | public static Test createTest(Class type, String name, String description) { 59 | if (name == null || name.isEmpty()) 60 | throw new IllegalArgumentException("Test name cannot be null or empty"); 61 | return Test.builder() 62 | .bddType(type) 63 | .name(name) 64 | .description(description) 65 | .endTime(Calendar.getInstance().getTime()).build(); 66 | } 67 | 68 | public static Test createTest(String name, String description) { 69 | return createTest(null, name, description); 70 | } 71 | 72 | public static Test createTest(String name) { 73 | return createTest(name, null); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/model/service/util/ExceptionUtil.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.model.service.util; 2 | 3 | import java.io.PrintWriter; 4 | import java.io.StringWriter; 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | public class ExceptionUtil { 9 | 10 | private ExceptionUtil() { 11 | } 12 | 13 | public static String getStackTrace(Throwable t) { 14 | if (t == null) 15 | return null; 16 | StringWriter sw = new StringWriter(); 17 | PrintWriter pw = new PrintWriter(sw); 18 | t.printStackTrace(pw); 19 | return sw.toString(); 20 | } 21 | 22 | public static String getExceptionHeadline(Throwable t) { 23 | Pattern pattern = Pattern.compile("([\\w\\.]+)(:.*)?"); 24 | String stackTrace = getStackTrace(t); 25 | Matcher matcher = pattern.matcher(stackTrace); 26 | if (matcher.find()) 27 | return matcher.group(1); 28 | return null; 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observable/ObservableList.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observable; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import com.aventstack.extentreports.model.BaseEntity; 8 | 9 | import io.reactivex.rxjava3.core.Observable; 10 | import io.reactivex.rxjava3.core.Observer; 11 | import io.reactivex.rxjava3.subjects.PublishSubject; 12 | import lombok.Getter; 13 | 14 | @Getter 15 | public class ObservableList { 16 | private final List list = Collections.synchronizedList(new ArrayList<>()); 17 | private final PublishSubject observable = PublishSubject.create(); 18 | 19 | public void subscribe(Observer observer) { 20 | observable.subscribe(observer); 21 | } 22 | 23 | public void add(T value) { 24 | list.add(value); 25 | observable.onNext(value); 26 | } 27 | 28 | public void remove(T value) { 29 | 30 | } 31 | 32 | public Observable getObservable() { 33 | return observable; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/AttributesObserver.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer; 2 | 3 | import com.aventstack.extentreports.observer.entity.AttributeEntity; 4 | import com.aventstack.extentreports.observer.entity.ObservedEntity; 5 | 6 | import io.reactivex.rxjava3.core.Observer; 7 | 8 | public interface AttributesObserver extends ExtentObserver { 9 | Observer getAttributesObserver(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/EntityObserver.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer; 2 | 3 | import com.aventstack.extentreports.observer.entity.ObservedEntity; 4 | 5 | public interface EntityObserver 6 | extends 7 | AttributesObserver, 8 | LogObserver, 9 | MediaObserver, 10 | ReportObserver, 11 | TestObserver { 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/ExtentObserver.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer; 2 | 3 | import com.aventstack.extentreports.observer.entity.ObservedEntity; 4 | 5 | public interface ExtentObserver { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/LogObserver.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer; 2 | 3 | import com.aventstack.extentreports.observer.entity.LogEntity; 4 | import com.aventstack.extentreports.observer.entity.ObservedEntity; 5 | 6 | import io.reactivex.rxjava3.core.Observer; 7 | 8 | public interface LogObserver extends ExtentObserver { 9 | Observer getLogObserver(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/MediaObserver.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer; 2 | 3 | import com.aventstack.extentreports.observer.entity.MediaEntity; 4 | import com.aventstack.extentreports.observer.entity.ObservedEntity; 5 | 6 | import io.reactivex.rxjava3.core.Observer; 7 | 8 | public interface MediaObserver extends ExtentObserver { 9 | Observer getMediaObserver(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/ReportObserver.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer; 2 | 3 | import com.aventstack.extentreports.observer.entity.ObservedEntity; 4 | import com.aventstack.extentreports.observer.entity.ReportEntity; 5 | 6 | import io.reactivex.rxjava3.core.Observer; 7 | 8 | public interface ReportObserver extends ExtentObserver { 9 | Observer getReportObserver(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/TestObserver.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer; 2 | 3 | import com.aventstack.extentreports.observer.entity.ObservedEntity; 4 | import com.aventstack.extentreports.observer.entity.TestEntity; 5 | 6 | import io.reactivex.rxjava3.core.Observer; 7 | 8 | public interface TestObserver extends ExtentObserver { 9 | Observer getTestObserver(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/entity/AttributeEntity.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer.entity; 2 | 3 | import com.aventstack.extentreports.model.Author; 4 | import com.aventstack.extentreports.model.Category; 5 | import com.aventstack.extentreports.model.Device; 6 | import com.aventstack.extentreports.model.Test; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Builder; 10 | import lombok.Getter; 11 | import lombok.Setter; 12 | 13 | @AllArgsConstructor 14 | @Getter 15 | @Setter 16 | @Builder 17 | public class AttributeEntity implements ObservedEntity { 18 | private Test test; 19 | private Author author; 20 | private Category category; 21 | private Device device; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/entity/LogEntity.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer.entity; 2 | 3 | import com.aventstack.extentreports.model.Log; 4 | import com.aventstack.extentreports.model.Test; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | @AllArgsConstructor 12 | @Getter 13 | @Setter 14 | @Builder 15 | public class LogEntity implements ObservedEntity { 16 | private Log log; 17 | private Test test; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/entity/MediaEntity.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer.entity; 2 | 3 | import com.aventstack.extentreports.model.Log; 4 | import com.aventstack.extentreports.model.Media; 5 | import com.aventstack.extentreports.model.Test; 6 | 7 | import lombok.AllArgsConstructor; 8 | import lombok.Builder; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | 12 | @AllArgsConstructor 13 | @Getter 14 | @Setter 15 | @Builder 16 | public class MediaEntity implements ObservedEntity { 17 | private Media media; 18 | private Test test; 19 | private Log log; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/entity/NamedAttributeTestEntity.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer.entity; 2 | 3 | import com.aventstack.extentreports.model.NamedAttribute; 4 | import com.aventstack.extentreports.model.Test; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | @Getter 12 | @Setter 13 | @AllArgsConstructor 14 | @Builder 15 | public class NamedAttributeTestEntity implements ObservedEntity { 16 | private NamedAttribute attribute; 17 | private Test test; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/entity/ObservedEntity.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer.entity; 2 | 3 | public interface ObservedEntity { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/entity/ReportEntity.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer.entity; 2 | 3 | import com.aventstack.extentreports.model.Report; 4 | 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | @AllArgsConstructor 11 | @Getter 12 | @Setter 13 | @Builder 14 | public class ReportEntity implements ObservedEntity { 15 | private Report report; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/observer/entity/TestEntity.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer.entity; 2 | 3 | import com.aventstack.extentreports.model.Test; 4 | 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | @AllArgsConstructor 11 | @Getter 12 | @Setter 13 | @Builder 14 | public class TestEntity implements ObservedEntity { 15 | private Test test; 16 | @Builder.Default 17 | private Boolean removed = false; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/AbstractFilterableReporter.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter; 2 | 3 | import java.util.Set; 4 | 5 | import com.aventstack.extentreports.Status; 6 | import com.aventstack.extentreports.model.Report; 7 | import com.aventstack.extentreports.model.service.ReportFilterService; 8 | import com.aventstack.extentreports.reporter.filter.StatusFilterable; 9 | 10 | import lombok.Getter; 11 | 12 | @Getter 13 | public class AbstractFilterableReporter extends AbstractReporter implements StatusFilterable { 14 | @Override 15 | public Report filterAndGet(Report report, Set set) { 16 | if (report == null || report.getTestList().isEmpty()) 17 | return report; 18 | if (set != null) 19 | return ReportFilterService.filter(report, set); 20 | return report; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/AbstractReporter.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter; 2 | 3 | public abstract class AbstractReporter implements ExtentReporter { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/ExtentKlovReporter.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter; 2 | 3 | import java.io.IOException; 4 | 5 | import com.aventstack.extentreports.observer.ReportObserver; 6 | import com.aventstack.extentreports.observer.entity.ReportEntity; 7 | import com.aventstack.extentreports.reporter.klov.KlovReporterClient; 8 | 9 | import io.reactivex.rxjava3.core.Observer; 10 | import io.reactivex.rxjava3.disposables.Disposable; 11 | import lombok.Getter; 12 | import lombok.Setter; 13 | 14 | @Getter 15 | @Setter 16 | public class ExtentKlovReporter implements ReportObserver { 17 | private final KlovReporterClient client; 18 | private Disposable disposable; 19 | 20 | /** 21 | * Initializes the KlovReporter with project and report names 22 | * 23 | * @param url 24 | * Url string 25 | * @param projectName 26 | * Name of the project 27 | * @param reportName 28 | * Name of the report 29 | */ 30 | public ExtentKlovReporter(String url, String projectName, String reportName) { 31 | client = new KlovReporterClient(url, projectName, reportName); 32 | } 33 | 34 | /** 35 | * Initializes the KlovReporter with the project name 36 | * 37 | * @param projectName 38 | * Name of the project 39 | */ 40 | public ExtentKlovReporter(String url, String projectName) { 41 | this(url, projectName, null); 42 | } 43 | 44 | @Override 45 | public Observer getReportObserver() { 46 | return new Observer() { 47 | @Override 48 | public void onSubscribe(Disposable d) { 49 | disposable = d; 50 | } 51 | 52 | @Override 53 | public void onNext(ReportEntity value) { 54 | try { 55 | client.flush(value); 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | 61 | @Override 62 | public void onError(Throwable e) { 63 | } 64 | 65 | @Override 66 | public void onComplete() { 67 | disposable.dispose(); 68 | } 69 | }; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/ExtentReporter.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter; 2 | 3 | /** 4 | * Mark interface 5 | */ 6 | public interface ExtentReporter { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/JsonFormatter.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter; 2 | 3 | import java.io.File; 4 | import java.io.FileWriter; 5 | import java.io.IOException; 6 | import java.util.List; 7 | 8 | import com.aventstack.extentreports.model.Test; 9 | import com.aventstack.extentreports.observer.ReportObserver; 10 | import com.aventstack.extentreports.observer.entity.ReportEntity; 11 | import com.google.gson.Gson; 12 | import com.google.gson.GsonBuilder; 13 | 14 | import io.reactivex.rxjava3.core.Observer; 15 | import io.reactivex.rxjava3.disposables.Disposable; 16 | 17 | public class JsonFormatter extends AbstractFileReporter implements ReportObserver { 18 | private static final String FILE_NAME = "extent.json"; 19 | 20 | public JsonFormatter(File file) { 21 | super(file); 22 | } 23 | 24 | public JsonFormatter(String filePath) { 25 | super(new File(filePath)); 26 | } 27 | 28 | @Override 29 | public Observer getReportObserver() { 30 | return new Observer() { 31 | @Override 32 | public void onSubscribe(Disposable d) { 33 | } 34 | 35 | @Override 36 | public void onNext(ReportEntity value) { 37 | flush(value); 38 | } 39 | 40 | @Override 41 | public void onError(Throwable e) { 42 | } 43 | 44 | @Override 45 | public void onComplete() { 46 | } 47 | }; 48 | } 49 | 50 | private void flush(ReportEntity value) { 51 | GsonBuilder builder = new GsonBuilder(); 52 | Gson gson = builder.create(); 53 | final String filePath = getFile().isDirectory() 54 | ? getFile().getAbsolutePath() 55 | + PATH_SEP + FILE_NAME 56 | : getFile().getAbsolutePath(); 57 | try (FileWriter writer = new FileWriter(new File(filePath))) { 58 | List list = value.getReport().getTestList(); 59 | gson.toJson(list, writer); 60 | } catch (IOException e) { 61 | e.printStackTrace(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/ReporterConfigurable.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | public interface ReporterConfigurable { 7 | void loadJSONConfig(File jsonFile) throws IOException; 8 | void loadJSONConfig(String jsonString) throws IOException; 9 | void loadXMLConfig(File xmlFile) throws IOException; 10 | void loadXMLConfig(String xmlFile) throws IOException; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/ReporterFilterable.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter; 2 | 3 | import com.aventstack.extentreports.reporter.configuration.EntityFilters; 4 | 5 | @FunctionalInterface 6 | public interface ReporterFilterable { 7 | EntityFilters filter(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/AbstractConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration; 2 | 3 | import com.aventstack.extentreports.config.ConfigStore; 4 | import com.aventstack.extentreports.reporter.AbstractReporter; 5 | 6 | import lombok.Builder; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import lombok.experimental.SuperBuilder; 10 | 11 | @Getter 12 | @Setter 13 | @SuperBuilder 14 | public abstract class AbstractConfiguration { 15 | protected AbstractReporter reporter; 16 | private final ConfigStore store = new ConfigStore(); 17 | 18 | @Builder.Default 19 | private String timeStampFormat = "MMM d, yyyy hh:mm:ss a"; 20 | @Builder.Default 21 | private String reportName = ""; 22 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/EntityFilters.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration; 2 | 3 | import com.aventstack.extentreports.reporter.AbstractReporter; 4 | 5 | import lombok.Getter; 6 | import lombok.experimental.Accessors; 7 | 8 | @Getter 9 | @Accessors(fluent = true) 10 | public class EntityFilters { 11 | private final T reporter; 12 | private final StatusFilter statusFilter; 13 | 14 | public EntityFilters(T reporter) { 15 | this.reporter = reporter; 16 | statusFilter = new StatusFilter(this); 17 | } 18 | 19 | public T apply() { 20 | return reporter; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/FileReporterConfig.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.experimental.SuperBuilder; 7 | 8 | @Getter 9 | @Setter 10 | @SuperBuilder(builderMethodName = "with") 11 | public abstract class FileReporterConfig extends AbstractConfiguration { 12 | @Builder.Default 13 | private String encoding = "UTF-8"; 14 | @Builder.Default 15 | private String documentTitle = ""; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/InteractiveReporterConfig.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration; 2 | 3 | import lombok.Builder; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.experimental.SuperBuilder; 7 | 8 | @Getter 9 | @Setter 10 | @SuperBuilder 11 | public class InteractiveReporterConfig extends FileReporterConfig { 12 | @Builder.Default 13 | private Protocol protocol = Protocol.HTTP; 14 | @Builder.Default 15 | private Theme theme = Theme.STANDARD; 16 | @Builder.Default 17 | private boolean timelineEnabled = true; 18 | @Builder.Default 19 | private String css = ""; 20 | @Builder.Default 21 | private String js = ""; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/Protocol.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Protocol used to download CDN css/js resources for HTML reports 7 | */ 8 | public enum Protocol { 9 | @SerializedName(value = "http", alternate = {"HTTP"}) 10 | HTTP, 11 | @SerializedName(value = "https", alternate = {"HTTPS"}) 12 | HTTPS 13 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/StatusFilter.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | import com.aventstack.extentreports.Status; 9 | import com.aventstack.extentreports.reporter.AbstractReporter; 10 | 11 | import lombok.Getter; 12 | 13 | @Getter 14 | public class StatusFilter { 15 | private Set status; 16 | private EntityFilters configurer; 17 | 18 | public StatusFilter(EntityFilters configurer) { 19 | this.configurer = configurer; 20 | } 21 | 22 | @SuppressWarnings("unchecked") 23 | public EntityFilters as(Set status) { 24 | this.status = status; 25 | return (EntityFilters) configurer; 26 | } 27 | 28 | public EntityFilters as(List status) { 29 | return as(new HashSet<>(status)); 30 | } 31 | 32 | public EntityFilters as(Status[] status) { 33 | return as(Arrays.asList(status)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/Theme.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import lombok.Getter; 6 | 7 | /** 8 | * Available themes for the HTML reporter 9 | */ 10 | @Getter 11 | public enum Theme { 12 | @SerializedName(value = "standard", alternate = {"STANDARD"}) 13 | STANDARD("standard"), 14 | @SerializedName(value = "dark", alternate = {"DARK"}) 15 | DARK("dark"); 16 | 17 | private final String name; 18 | 19 | Theme(String name) { 20 | this.name = name.toLowerCase(); 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return name; 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/ViewConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration; 2 | 3 | import lombok.Getter; 4 | import lombok.experimental.Accessors; 5 | 6 | @Getter 7 | @Accessors(fluent = true) 8 | public class ViewConfigurer> { 9 | private final T reporter; 10 | private final ViewOrder viewOrder; 11 | 12 | public ViewConfigurer(T reporter) { 13 | this.reporter = reporter; 14 | viewOrder = new ViewOrder(this); 15 | } 16 | 17 | public T apply() { 18 | return reporter; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/ViewName.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration; 2 | 3 | public enum ViewName { 4 | AUTHOR, CATEGORY, DASHBOARD, DEVICE, EXCEPTION, LOG, TEST; 5 | 6 | @Override 7 | public String toString() { 8 | return this.name().toLowerCase(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/ViewOrder.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Getter 10 | @NoArgsConstructor 11 | public class ViewOrder> { 12 | private static final List DEFAULT_ORDER = Arrays.asList(new ViewName[]{ 13 | ViewName.TEST, 14 | ViewName.EXCEPTION, 15 | ViewName.CATEGORY, 16 | ViewName.DEVICE, 17 | ViewName.AUTHOR, 18 | ViewName.LOG, 19 | ViewName.DASHBOARD 20 | }); 21 | 22 | private List viewOrder = DEFAULT_ORDER; 23 | private ViewConfigurer configurer; 24 | 25 | public ViewOrder(ViewConfigurer configurer) { 26 | this.configurer = configurer; 27 | } 28 | 29 | @SuppressWarnings("unchecked") 30 | public ViewConfigurer as(List order) { 31 | this.viewOrder = order; 32 | return (ViewConfigurer) configurer; 33 | } 34 | 35 | public ViewConfigurer as(ViewName[] viewOrder) { 36 | return as(Arrays.asList(viewOrder)); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/ViewStyle.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration; 2 | 3 | public enum ViewStyle { 4 | DEFAULT, SPA 5 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/ViewsConfigurable.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration; 2 | 3 | public interface ViewsConfigurable { 4 | ViewConfigurer viewConfigurer(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/util/IOUtil.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration.util; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.net.URI; 9 | import java.nio.file.Files; 10 | import java.nio.file.Path; 11 | import java.nio.file.Paths; 12 | import java.nio.file.StandardCopyOption; 13 | import java.util.Arrays; 14 | 15 | public class IOUtil { 16 | private static final String SEP = "/"; 17 | 18 | private IOUtil() { 19 | } 20 | 21 | public static void createDirectory(String path) { 22 | new File(path).mkdirs(); 23 | } 24 | 25 | public static void createDirectory(String[] path) { 26 | Arrays.asList(path).forEach(IOUtil::createDirectory); 27 | } 28 | 29 | public static void moveResource(String resourcePath, String copyPath) { 30 | if (copyPath != null) 31 | copyPath = copyPath.replace("\\", SEP); 32 | if (resourcePath != null) 33 | resourcePath = resourcePath.replace("\\", SEP); 34 | try { 35 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 36 | InputStream in = classLoader.getResourceAsStream(resourcePath); 37 | FileOutputStream out = new FileOutputStream(copyPath); 38 | byte[] b = new byte[1024]; 39 | int noOfBytes = 0; 40 | while ((noOfBytes = in.read(b)) != -1) 41 | out.write(b, 0, noOfBytes); 42 | in.close(); 43 | out.close(); 44 | } catch (FileNotFoundException e) { 45 | e.printStackTrace(); 46 | } catch (IOException e) { 47 | e.printStackTrace(); 48 | } 49 | } 50 | 51 | public static void moveBinary(String resourcePath, String copyPath) { 52 | URI uri = new File(resourcePath).toURI(); 53 | Path path = Paths.get(uri); 54 | try { 55 | Files.copy(path, new File(copyPath).toPath(), StandardCopyOption.REPLACE_EXISTING); 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/configuration/util/ResourceHelper.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.configuration.util; 2 | 3 | import java.io.File; 4 | import java.nio.file.Path; 5 | import java.nio.file.Paths; 6 | import java.util.Arrays; 7 | 8 | public class ResourceHelper { 9 | private ResourceHelper() { 10 | 11 | } 12 | 13 | public static void saveOfflineResources(String baseDir, String[] resx, String toPath) { 14 | IOUtil.createDirectory(toPath); 15 | for (String f : resx) { 16 | Path path = Paths.get(baseDir, f); 17 | String fromPath = path.toString(); 18 | String toPathComplete = Paths.get(toPath, new File(f).getName()).toString(); 19 | IOUtil.moveResource(fromPath, toPathComplete); 20 | } 21 | } 22 | 23 | public static void saveOfflineResources(String[] resx, String toPath) { 24 | Arrays.stream(resx).forEach(x -> IOUtil.moveResource(x, toPath)); 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/filter/ContextFilter.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.filter; 2 | 3 | import java.util.Arrays; 4 | import java.util.Set; 5 | import java.util.stream.Collectors; 6 | import java.util.stream.Stream; 7 | 8 | import com.aventstack.extentreports.Status; 9 | 10 | import lombok.Getter; 11 | 12 | @Getter 13 | public class ContextFilter { 14 | private static final Builder BUILDER = new Builder(); 15 | private Set status; 16 | private Set author; 17 | private Set category; 18 | private Set device; 19 | 20 | public ContextFilter(Set status, Set author, Set category, Set device) { 21 | this.status = status; 22 | this.author = author; 23 | this.category = category; 24 | this.device = device; 25 | } 26 | 27 | public static Builder builder() { 28 | return BUILDER; 29 | } 30 | 31 | public static class Builder { 32 | private Set statusSet; 33 | private Set authorSet; 34 | private Set categorySet; 35 | private Set deviceSet; 36 | 37 | public Builder status(Set status) { 38 | this.statusSet = status; 39 | return this; 40 | } 41 | 42 | public Builder status(Status[] status) { 43 | return status(Arrays.stream(status).collect(Collectors.toSet())); 44 | } 45 | 46 | public Builder status(Status status) { 47 | return status(Stream.of(status).collect(Collectors.toSet())); 48 | } 49 | 50 | public Builder author(Set author) { 51 | this.authorSet = author; 52 | return this; 53 | } 54 | 55 | public Builder author(String[] author) { 56 | return author(Arrays.stream(author).collect(Collectors.toSet())); 57 | } 58 | 59 | public Builder author(String author) { 60 | return author(Stream.of(author).collect(Collectors.toSet())); 61 | } 62 | 63 | public Builder category(Set category) { 64 | this.categorySet = category; 65 | return this; 66 | } 67 | 68 | public Builder category(String[] category) { 69 | return category(Arrays.stream(category).collect(Collectors.toSet())); 70 | } 71 | 72 | public Builder category(String category) { 73 | return category(Stream.of(category).collect(Collectors.toSet())); 74 | } 75 | 76 | public Builder device(Set device) { 77 | this.deviceSet = device; 78 | return this; 79 | } 80 | 81 | public Builder device(String[] device) { 82 | return author(Arrays.stream(device).collect(Collectors.toSet())); 83 | } 84 | 85 | public Builder device(String device) { 86 | return author(Stream.of(device).collect(Collectors.toSet())); 87 | } 88 | 89 | public ContextFilter build() { 90 | return new ContextFilter(statusSet, authorSet, categorySet, deviceSet); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/filter/StatusFilterable.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.filter; 2 | 3 | import java.util.Set; 4 | 5 | import com.aventstack.extentreports.Status; 6 | import com.aventstack.extentreports.model.Report; 7 | 8 | @FunctionalInterface 9 | public interface StatusFilterable { 10 | Report filterAndGet(Report report, Set set); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/KlovReporterClient.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov; 2 | 3 | import java.io.IOException; 4 | import java.net.URISyntaxException; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | 8 | import org.apache.http.HttpResponse; 9 | import org.apache.http.client.ClientProtocolException; 10 | import org.apache.http.client.methods.HttpPost; 11 | import org.apache.http.entity.ContentType; 12 | import org.apache.http.entity.StringEntity; 13 | import org.apache.http.impl.client.CloseableHttpClient; 14 | import org.apache.http.impl.client.HttpClients; 15 | 16 | import com.aventstack.extentreports.model.Report; 17 | import com.aventstack.extentreports.model.Test; 18 | import com.aventstack.extentreports.observer.entity.ReportEntity; 19 | import com.aventstack.extentreports.reporter.klov.entity.KlovProject; 20 | import com.aventstack.extentreports.reporter.klov.entity.KlovURI; 21 | import com.aventstack.extentreports.reporter.klov.util.URIUtil; 22 | import com.google.gson.Gson; 23 | 24 | public class KlovReporterClient { 25 | private final ExecutorService executor = Executors.newSingleThreadExecutor(); 26 | private final String url; 27 | private final String projectName; 28 | private final String reportName; 29 | 30 | public KlovReporterClient(String url, String projectName, String reportName) { 31 | this.url = url; 32 | this.projectName = projectName; 33 | this.reportName = reportName; 34 | try { 35 | init(); 36 | } catch (IOException e) { 37 | // TODO Auto-generated catch block 38 | e.printStackTrace(); 39 | } catch (URISyntaxException e) { 40 | // TODO Auto-generated catch block 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | private final void init() throws ClientProtocolException, IOException, URISyntaxException { 46 | KlovProject project = new KlovProject(null, projectName); 47 | String json = new Gson().toJson(project); 48 | StringEntity requestEntity = new StringEntity( 49 | json, 50 | ContentType.APPLICATION_JSON); 51 | HttpPost postMethod = new HttpPost(URIUtil.build(url, KlovURI.PROJECT)); 52 | postMethod.setEntity(requestEntity); 53 | CloseableHttpClient httpclient = HttpClients.createDefault(); 54 | HttpResponse response = httpclient.execute(postMethod); 55 | System.out.println(response); 56 | } 57 | 58 | public void flush(ReportEntity entity) throws ClientProtocolException, IOException { 59 | Report report = entity.getReport(); 60 | putReport(report); 61 | report.getTestList().forEach(this::postTest); 62 | } 63 | 64 | private void putReport(Report report) { 65 | // KlovReport r = new KlovReport(report); 66 | // System.out.println(r.toString()); 67 | } 68 | 69 | private void postTest(Test test) { 70 | // KlovTest t = new KlovTest(test, null); 71 | // System.out.println(t.toString()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/entity/KlovAttribute.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov.entity; 2 | 3 | import java.util.List; 4 | 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | 10 | @Getter 11 | @Setter 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public abstract class KlovAttribute { 15 | protected String project; 16 | protected String report; 17 | protected String name; 18 | protected Long timeTaken; 19 | protected List testId; 20 | protected List testName; 21 | protected Integer testCount; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/entity/KlovAuthor.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov.entity; 2 | 3 | import lombok.ToString; 4 | 5 | @ToString(callSuper = true) 6 | public class KlovAuthor extends KlovAttribute { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/entity/KlovCategory.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov.entity; 2 | 3 | import lombok.ToString; 4 | 5 | @ToString(callSuper = true) 6 | public class KlovCategory extends KlovAttribute { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/entity/KlovDevice.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov.entity; 2 | 3 | import lombok.ToString; 4 | 5 | @ToString(callSuper = true) 6 | public class KlovDevice extends KlovAttribute { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/entity/KlovEntity.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | @AllArgsConstructor 10 | public class KlovEntity { 11 | private String projectName; 12 | private String projectId; 13 | private String reportName; 14 | private String reportId; 15 | private int reportSeq; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/entity/KlovEnvironment.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | @Getter 10 | @Setter 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | @ToString 14 | public class KlovEnvironment { 15 | private String id; 16 | private String project; 17 | private String report; 18 | private String name; 19 | private String value; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/entity/KlovExceptionEvent.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class KlovExceptionEvent { 13 | private String id; 14 | private String project; 15 | private String report; 16 | private String name; 17 | private String stacktrace; 18 | private Integer testCount; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/entity/KlovLog.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov.entity; 2 | 3 | import java.util.Date; 4 | 5 | import com.aventstack.extentreports.model.Log; 6 | import com.aventstack.extentreports.model.Test; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Getter; 10 | import lombok.NoArgsConstructor; 11 | import lombok.Setter; 12 | 13 | @Getter 14 | @Setter 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class KlovLog { 18 | private String project; 19 | private String report; 20 | private String test; 21 | private String testName; 22 | private Integer sequence; 23 | private String status; 24 | private String details; 25 | private String exception; 26 | private String stacktrace; 27 | private Date timestamp; 28 | private Integer mediaCount; 29 | private KlovMedia media; 30 | 31 | public KlovLog(KlovEntity entity) { 32 | project = entity.getProjectId(); 33 | report = entity.getReportId(); 34 | } 35 | 36 | public KlovLog transform(Log log, Test test) { 37 | sequence = log.getSeq(); 38 | status = log.getStatus().toLower(); 39 | details = log.getDetails(); 40 | if (log.hasException()) { 41 | exception = log.getException().getName(); 42 | stacktrace = log.getException().getStackTrace(); 43 | } 44 | timestamp = log.getTimestamp(); 45 | if (log.hasMedia()) { 46 | mediaCount = 1; 47 | media = new KlovMedia(log.getMedia()); 48 | } 49 | return this; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/entity/KlovMedia.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov.entity; 2 | 3 | import com.aventstack.extentreports.model.Media; 4 | import com.aventstack.extentreports.model.ScreenCapture; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Getter; 8 | import lombok.NoArgsConstructor; 9 | import lombok.Setter; 10 | 11 | @Getter 12 | @Setter 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class KlovMedia { 16 | private String test; 17 | private String log; 18 | private String project; 19 | private String report; 20 | private Integer sequence; 21 | private String testName; 22 | private String path; 23 | private String mediaType; 24 | private String ext; 25 | private String base64String; 26 | 27 | public KlovMedia(Media m) { 28 | transform((ScreenCapture) m); 29 | } 30 | 31 | private void transform(ScreenCapture sc) { 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/entity/KlovProject.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class KlovProject { 13 | private String id; 14 | private String name; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/entity/KlovURI.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov.entity; 2 | 3 | public class KlovURI { 4 | public static final String PROJECT = "/api/projects"; 5 | public static final String REPORT = "/api/reports"; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/reporter/klov/util/URIUtil.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.reporter.klov.util; 2 | 3 | import java.net.URI; 4 | import java.net.URISyntaxException; 5 | 6 | import org.apache.http.client.utils.URIBuilder; 7 | 8 | public class URIUtil { 9 | public static URI build(String host, String path) throws URISyntaxException { 10 | URIBuilder builder = new URIBuilder(host); 11 | builder.setPath(path); 12 | URI uri = builder.build(); 13 | return uri; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/templating/FreemarkerTemplate.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.templating; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.StringWriter; 6 | import java.util.Map; 7 | 8 | import com.aventstack.extentreports.io.BufferedWriterWriter; 9 | 10 | import freemarker.core.ParseException; 11 | import freemarker.template.Configuration; 12 | import freemarker.template.MalformedTemplateNameException; 13 | import freemarker.template.Template; 14 | import freemarker.template.TemplateException; 15 | import freemarker.template.TemplateNotFoundException; 16 | 17 | public class FreemarkerTemplate { 18 | private final TemplateConfig templateConfig = new TemplateConfig(); 19 | private final Configuration freemarkerConfig; 20 | 21 | public FreemarkerTemplate(Configuration freemarkerConfiguration) { 22 | this.freemarkerConfig = freemarkerConfiguration; 23 | } 24 | 25 | public FreemarkerTemplate(Class clazz, String encoding) { 26 | freemarkerConfig = templateConfig.getFreemarkerConfig(clazz, encoding); 27 | } 28 | 29 | public FreemarkerTemplate(Class clazz, String basePackagePath, String encoding) { 30 | freemarkerConfig = templateConfig.getFreemarkerConfig(clazz, basePackagePath, encoding); 31 | } 32 | 33 | public Template createTemplate(String templatePath) 34 | throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException { 35 | return freemarkerConfig.getTemplate(templatePath); 36 | } 37 | 38 | public String getSource(Template template, Map templateMap) throws TemplateException, IOException { 39 | String source = processTemplate(template, templateMap); 40 | return source; 41 | } 42 | 43 | public void writeTemplate(Template template, Map templateMap, File outputFile) 44 | throws TemplateException, IOException { 45 | String source = getSource(template, templateMap); 46 | BufferedWriterWriter.getInstance().write(outputFile, source); 47 | } 48 | 49 | private String processTemplate(Template template, Map templateMap) 50 | throws TemplateException, IOException { 51 | StringWriter out = new StringWriter(); 52 | template.process(templateMap, out); 53 | String source = out.toString(); 54 | out.close(); 55 | return source; 56 | } 57 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/templating/TemplateConfig.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.templating; 2 | 3 | import freemarker.template.Configuration; 4 | 5 | public class TemplateConfig { 6 | public Configuration getFreemarkerConfig(Class clazz, String basePackagePath, String encoding) { 7 | Configuration cfg = new Configuration(Configuration.VERSION_2_3_30); 8 | cfg.setClassForTemplateLoading(clazz, basePackagePath); 9 | cfg.setDefaultEncoding(encoding); 10 | cfg.setAPIBuiltinEnabled(true); 11 | return cfg; 12 | } 13 | 14 | public Configuration getFreemarkerConfig(Class clazz, String encoding) { 15 | return getFreemarkerConfig(clazz, "/", encoding); 16 | } 17 | } -------------------------------------------------------------------------------- /src/main/java/com/aventstack/extentreports/view/Ico.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.view; 2 | 3 | import java.util.Arrays; 4 | 5 | public enum Ico { 6 | INFO("Info", "info"), PASS("Pass", "check"), SKIP("Skip", "long-arrow-right"), WARNING("Warning", 7 | "warning"), FAIL("Fail", "times"), RETRY("Retry", "reset"); 8 | 9 | private final String name; 10 | private final String ico; 11 | 12 | Ico(String name, String ico) { 13 | this.name = name; 14 | this.ico = ico; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public String getIco() { 22 | return ico; 23 | } 24 | 25 | public static Ico ico(String name) { 26 | return Arrays.stream(values()) 27 | .filter(x -> x.name.equalsIgnoreCase(name)) 28 | .findAny() 29 | .orElse(null); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return ico; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/markup/codeblock.ftl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/markup/codeblock.json.ftl: -------------------------------------------------------------------------------- 1 |
    2 | 8 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/offline/commons/css/icons/fontawesome/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anshooarora/extentreports-java/925c18aac5e7fe935676822f33803ab0444208e6/src/main/resources/com/aventstack/extentreports/offline/commons/css/icons/fontawesome/FontAwesome.otf -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/offline/commons/css/icons/fontawesome/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anshooarora/extentreports-java/925c18aac5e7fe935676822f33803ab0444208e6/src/main/resources/com/aventstack/extentreports/offline/commons/css/icons/fontawesome/fontawesome-webfont.eot -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/offline/commons/css/icons/fontawesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anshooarora/extentreports-java/925c18aac5e7fe935676822f33803ab0444208e6/src/main/resources/com/aventstack/extentreports/offline/commons/css/icons/fontawesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/offline/commons/css/icons/fontawesome/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anshooarora/extentreports-java/925c18aac5e7fe935676822f33803ab0444208e6/src/main/resources/com/aventstack/extentreports/offline/commons/css/icons/fontawesome/fontawesome-webfont.woff -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/offline/commons/css/icons/fontawesome/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anshooarora/extentreports-java/925c18aac5e7fe935676822f33803ab0444208e6/src/main/resources/com/aventstack/extentreports/offline/commons/css/icons/fontawesome/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/offline/commons/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anshooarora/extentreports-java/925c18aac5e7fe935676822f33803ab0444208e6/src/main/resources/com/aventstack/extentreports/offline/commons/img/logo.png -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/offline/commons/js/jsontree.js: -------------------------------------------------------------------------------- 1 | /*! json-tree - v0.2.2 - 2017-09-25, MIT LICENSE */ 2 | var JSONTree=function(){var n={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},t=0,r=0;this.create=function(n,t){return r+=1,N(u(n,0,!1),{class:"jstValue"})};var e=function(t){return t.replace(/[&<>'"]/g,function(t){return n[t]})},s=function(){return r+"_"+t++},u=function(n,t,r){if(null===n)return f(r?t:0);switch(typeof n){case"boolean":return l(n,r?t:0);case"number":return i(n,r?t:0);case"string":return o(n,r?t:0);default:return n instanceof Array?a(n,t,r):c(n,t,r)}},c=function(n,t,r){var e=s(),u=Object.keys(n).map(function(r){return j(r,n[r],t+1,!0)}).join(m()),c=[g("{",r?t:0,e),N(u,{id:e}),p("}",t)].join("\n");return N(c,{})},a=function(n,t,r){var e=s(),c=n.map(function(n){return u(n,t+1,!0)}).join(m());return[g("[",r?t:0,e),N(c,{id:e}),p("]",t)].join("\n")},o=function(n,t){var r=e(JSON.stringify(n));return N(v(r,t),{class:"jstStr"})},i=function(n,t){return N(v(n,t),{class:"jstNum"})},l=function(n,t){return N(v(n,t),{class:"jstBool"})},f=function(n){return N(v("null",n),{class:"jstNull"})},j=function(n,t,r){var s=v(e(JSON.stringify(n))+": ",r),c=N(u(t,r,!1),{});return N(s+c,{class:"jstProperty"})},m=function(){return N(",\n",{class:"jstComma"})},N=function(n,t){return d("span",t,n)},d=function(n,t,r){return"<"+n+Object.keys(t).map(function(n){return" "+n+'="'+t[n]+'"'}).join("")+">"+r+""},g=function(n,t,r){return N(v(n,t),{class:"jstBracket"})+N("",{class:"jstFold",onclick:"JSONTree.toggle('"+r+"')"})};this.toggle=function(n){var t=document.getElementById(n),r=t.parentNode,e=t.previousElementSibling;""===t.className?(t.className="jstHiddenBlock",r.className="jstFolded",e.className="jstExpand"):(t.className="",r.className="",e.className="jstFold")};var p=function(n,t){return N(v(n,t),{})},v=function(n,t){return Array(2*t+1).join(" ")+n};return this}(); 3 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/offline/spark/css/spark-style.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anshooarora/extentreports-java/925c18aac5e7fe935676822f33803ab0444208e6/src/main/resources/com/aventstack/extentreports/offline/spark/css/spark-style.css -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/commons/commons-exception.ftl: -------------------------------------------------------------------------------- 1 | <#include "commons-macros.ftl"> 2 | 3 |
    4 | 47 |
    -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/commons/commons-inject-css.ftl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/commons/commons-inject-js.ftl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/commons/commons-macros.ftl: -------------------------------------------------------------------------------- 1 | <#macro attributes test> 2 | <#if test.hasCategory()> 3 | 4 | <#list test.categoryContext.all as category> 5 | ${category.name} 6 | 7 | 8 | 9 | <#if test.hasAuthor()> 10 | 11 | <#list test.authorContext.all as author> 12 | ${author.name} 13 | 14 | 15 | 16 | <#if test.hasDevice()> 17 | 18 | <#list test.deviceContext.all as device> 19 | ${device.name} 20 | 21 | 22 | 23 | 24 | 25 | <#macro media media> 26 | <#if media?? && media?is_enumerable><#list media as m><@mediaSingle m /> 27 | <#else><@mediaSingle media /> 28 | 29 | 30 | 31 | <#macro mediaSingle m> 32 | <#if m??> 33 |
    34 | <#if m.base64??> 35 | <#elseif m.resolvedPath??> 36 | <#elseif m.path??> 37 | 38 |
    39 | 40 | 41 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/commons/commons-tag.ftl: -------------------------------------------------------------------------------- 1 | <#include "commons-macros.ftl"> 2 | 3 |
    4 | 57 |
    -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/commons/commons-variables.ftl: -------------------------------------------------------------------------------- 1 | <#assign 2 | config=this.config() 3 | theme=config.theme?lower_case 4 | timeStampFormat=config.timeStampFormat 5 | offline=config.offlineMode 6 | reportType="" 7 | parentHeading="Tests" 8 | childHeading="Steps" 9 | grandChildHeading="" 10 | displayEvents=true 11 | chartWidth="115" 12 | chartHeight="90" 13 | chartBoxHeight="94" 14 | displayEvents=true> 15 | <#if report.stats.analysisStrategy=="SUITE"> 16 | <#assign 17 | parentHeading="Suite" 18 | childHeading="Class" 19 | grandChildHeading="Test"> 20 | 21 | <#if report.stats.analysisStrategy=="CLASS"> 22 | <#assign 23 | parentHeading="Class" 24 | childHeading="Methods" 25 | grandChildHeading=""> 26 | 27 | <#assign chartCount=2> 28 | <#if report.stats.sumStat(report.stats.child) != 0><#assign chartCount=3> 29 | <#if report.stats.sumStat(report.stats.grandchild) != 0><#assign chartCount=4> 30 | <#if report.isBDD()> 31 | <#assign 32 | reportType="bdd" 33 | parentHeading="Features" 34 | childHeading="Scenarios" 35 | grandChildHeading="Steps" 36 | chartCount=3 37 | displayEvents=false> 38 | 39 | <#assign 40 | boxsize="col-md-"+(12/chartCount)> -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/dashboard.ftl: -------------------------------------------------------------------------------- 1 | <#include "../commons/commons-variables.ftl"> 2 | 3 | 4 | 5 | <#include "partials/head.ftl"> 6 | 7 |
    8 |
    9 | <#include "partials/navbar.ftl"> 10 | <#include "partials/sidenav.ftl"> 11 |
    12 |
    13 | <#include "partials/dashboard.ftl"> 14 |
    15 |
    16 |
    17 |
    18 | <#include "partials/scripts.ftl"> 19 | 20 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/exception.ftl: -------------------------------------------------------------------------------- 1 | <#include "../commons/commons-variables.ftl"> 2 | 3 | 4 | 5 | <#include "partials/head.ftl"> 6 | 7 |
    8 |
    9 | <#include "partials/navbar.ftl"> 10 | <#include "partials/sidenav.ftl"> 11 |
    12 |
    13 | <#include "partials/exception.ftl"> 14 |
    15 |
    16 |
    17 |
    18 | <#include "partials/scripts.ftl"> 19 | 20 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/macros/attributes.ftl: -------------------------------------------------------------------------------- 1 | <#macro attributes test> 2 | <#compress> 3 | <#if test.hasAuthor()> 4 | <#list test.authorSet as author> 5 | ${author.name} 6 | 7 | 8 | <#if test.hasCategory()> 9 | <#list test.categorySet as category> 10 | ${category.name} 11 | 12 | 13 | <#if test.hasDevice()> 14 | <#list test.deviceSet as device> 15 | ${device.name} 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/macros/log.ftl: -------------------------------------------------------------------------------- 1 | <#macro log test> 2 | 3 | 4 | 5 | <#list test.logs as log> 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 |
    StatusTimestampDetails
    ${log.status?string}${log.timestamp?time?string} 10 | <#if log.exception??> 11 | <#else>${log.details} 12 | <#if log.media??><@mediaSingle log.media /> 13 |
    18 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/macros/recurse_nodes.ftl: -------------------------------------------------------------------------------- 1 | <#include "log.ftl"> 2 | <#macro recurse_nodes test> 3 | <#if test.hasChildren()> 4 |
    5 | <#list test.children as node> 6 |
    7 |
    8 |
    9 |
    ${node.name}
    10 |
    11 | 12 |
    13 | <#if TestService.testHasScreenCapture(node, true)> 14 |
    15 | 16 |
    17 |
    18 | <#if node.hasLog()> 19 |
    20 |
    21 | <@log test=node /> 22 | <@media node.media /> 23 |
    24 |
    25 | 26 | <#if test.hasChildren()> 27 | <@recurse_nodes test=node /> 28 | 29 |
    30 | 31 |
    32 | 33 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/partials/bdd-content.ftl: -------------------------------------------------------------------------------- 1 | <#macro stepdetails test> 2 | <#if test.hasLog()> 3 | <#list test.logs as log> 4 |
    <#if log.exception??> 5 | 6 | <#else>${log.details} 7 | <#if log.media??><@mediaSingle log.media />
    8 | 9 | 10 | 11 | 12 | <#if test.hasChildren()> 13 |
    14 | <#list test.children as node> 15 |
    16 | 26 | <#if test.hasChildren()> 27 | <#if node.bddType?? && node.bddType.simpleName=="ScenarioOutline"> 28 |
    29 | <#list node.children as child> 30 |
    31 |
    32 |
    33 |
    ${child.status?string}${child.name}
    34 | <#if TestService.testHasScreenCapture(child, true)> 35 |
    36 | 37 |
    38 | 39 |
    40 |
    41 |
    42 | <#list child.children as step> 43 |
    44 | ${step.name} 45 | <@stepdetails test=step /> 46 |
    47 | 48 |
    49 |
    50 | 51 |
    52 | <#else> 53 |
    54 |
    55 | <#list node.children as child> 56 |
    title="${child.description}"> 57 | ${child.name} 58 | <@stepdetails test=child /> 59 |
    60 | 61 |
    62 |
    63 | 64 | 65 |
    66 | 67 |
    68 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/partials/exception.ftl: -------------------------------------------------------------------------------- 1 | <#if report.exceptionInfoCtx.set?size != 0> 2 | <#assign 3 | exceptionInfoCtx=report.exceptionInfoCtx.set> 4 | <#compress> 5 |
    6 |
    7 |
    8 | 15 | 22 |
    23 |
    24 |
      25 | <#list exceptionInfoCtx as context> 26 |
    • 27 |
      28 |
      29 |

      ${context.attr.name}

      30 |

      ${context.testList?size} tests

      31 |
      32 |
      33 |
      34 |
      35 |

      ${context.attr.name}

      36 |
      37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | <#list context.testList as test> 47 | 48 | 49 | 50 | 58 | 59 | 60 | 61 |
      StatusTimestampTestName
      ${test.status?string}${test.startTime?string[("HH:mm:ss a")]} 51 | ${test.name} 52 | <#if test.parent??> 53 |
      54 | ${test.parent.name} 55 |
      56 | 57 |
      62 |
      63 |
    • 64 | 65 |
    66 |
    67 |
    68 |
    69 |
    70 | 77 |
    78 |
    79 |
    80 |
    81 |
    82 |
    83 | 84 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/partials/head.ftl: -------------------------------------------------------------------------------- 1 | <#compress> 2 | <#assign 3 | resourceCDN=config.resourceCDN 4 | cdnURI="cdn.jsdelivr.net/gh/extent-framework/extent-github-cdn@" 5 | csscommit="5689f93cdb7cd5ee4d33d8ae2c849856b1dd42df" 6 | jscommit="f65aac917aab907884a5bcdf2fed41777ea51948" 7 | iconcommit="b00a2d0486596e73dd7326beacf352c639623a0e"> 8 | <#if resourceCDN=="extentreports"> 9 | <#assign 10 | cdnURI="extentreports.com/resx" 11 | csscommit="" 12 | jscommit="" 13 | iconcommit=""> 14 | 15 | 16 | 17 | 18 | 19 | ${config.documentTitle} 20 | <#if offline> 21 | 22 | 23 | 24 | 25 | 26 | <#else> 27 | 28 | 29 | 30 | 31 | 32 | 33 | <#include "../../commons/commons-inject-css.ftl"> 34 | 35 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/partials/log.ftl: -------------------------------------------------------------------------------- 1 | <#if report.logs?size != 0> 2 |
    3 |
    4 |
    5 | <#list report.logs as log>${ log } 6 |
    7 |
    8 |
    9 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/partials/logs.ftl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anshooarora/extentreports-java/925c18aac5e7fe935676822f33803ab0444208e6/src/main/resources/com/aventstack/extentreports/templates/spark/partials/logs.ftl -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/partials/navbar.ftl: -------------------------------------------------------------------------------- 1 | <#compress> 2 | 30 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/partials/scripts.ftl: -------------------------------------------------------------------------------- 1 | <#if offline> 2 | <#else> 3 | 4 | <#include "../../commons/commons-inject-js.ftl"> 5 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/partials/sidenav.ftl: -------------------------------------------------------------------------------- 1 | <#compress> 2 |
    3 |
    4 |
      5 | <#list viewOrder as order> 6 | <#if order.toString()!="logs"> 7 | <#if 8 | order.toString()=="exception" && report.exceptionInfoCtx.hasItems() 9 | || order.toString()=="category" && report.categoryCtx.hasItems() 10 | || order.toString()=="device" && report.deviceCtx.hasItems() 11 | || order.toString()=="author" && report.authorCtx.hasItems() 12 | || order.toString()=="log" && report.logs?size != 0 13 | || order.toString()=="test" || order.toString()=="dashboard"> 14 | <#assign ico="list"> 15 | <#if order.toString()=="category"><#assign ico="tag"> 16 | <#elseif order.toString()=="exception"><#assign ico="bug"> 17 | <#elseif order.toString()=="device"><#assign ico="tablet"> 18 | <#elseif order.toString()=="author"><#assign ico="user"> 19 | <#elseif order.toString()=="dashboard"><#assign ico="bar-chart"> 20 | <#elseif order.toString()=="log"><#assign ico="clipboard"> 21 | 22 | 27 | 28 | 29 | 30 |
    31 |
    32 |
    33 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/partials/standard-content.ftl: -------------------------------------------------------------------------------- 1 | <@media test.media /> 2 | <#if test.hasAnyLog()> 3 |
    4 | <#list test.generatedLog as l>${l.details} 5 | <#if test.hasLog()><@log test=test /> 6 |
    7 | 8 | <#if test.hasChildren()> 9 |
    <@recurse_nodes test=test />
    10 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/spark.spa.ftl: -------------------------------------------------------------------------------- 1 | <#include "../commons/commons-variables.ftl"> 2 | <#include "../commons/commons-macros.ftl"> 3 | <#include "macros/attributes.ftl"> 4 | <#include "macros/log.ftl"> 5 | <#include "macros/recurse_nodes.ftl"> 6 | 7 | <#assign 8 | isbdd=false 9 | pageClass=""> 10 | <#if report.isBDD()> 11 | <#assign 12 | pageClass="bdd" 13 | isbdd=true> 14 | 15 | 16 | 17 | 18 | <#include "partials/head.ftl"> 19 | 20 |
    21 |
    22 | <#include "partials/navbar.ftl"> 23 | <#include "partials/sidenav.ftl"> 24 |
    25 |
    26 | <#list viewOrder as view><#include "partials/${view.toString()}.ftl"> 27 |
    28 |
    29 |
    30 |
    31 | <#include "partials/scripts.ftl"> 32 | 33 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/tag.ftl: -------------------------------------------------------------------------------- 1 | <#include "../commons/commons-variables.ftl"> 2 | 3 | 4 | 5 | <#include "partials/head.ftl"> 6 | 7 |
    8 |
    9 | <#include "partials/navbar.ftl"> 10 | <#include "partials/sidenav.ftl"> 11 |
    12 |
    13 | <#include "partials/tag.ftl"> 14 |
    15 |
    16 |
    17 |
    18 | <#include "partials/scripts.ftl"> 19 | 20 | -------------------------------------------------------------------------------- /src/main/resources/com/aventstack/extentreports/templates/spark/test.ftl: -------------------------------------------------------------------------------- 1 | <#include "../commons/commons-variables.ftl"> 2 | <#include "../commons/commons-macros.ftl"> 3 | <#include "macros/attributes.ftl"> 4 | <#include "macros/log.ftl"> 5 | <#include "macros/recurse_nodes.ftl"> 6 | 7 | <#assign 8 | isbdd=false 9 | pageClass=""> 10 | <#if report.isBDD()> 11 | <#assign 12 | pageClass="bdd" 13 | isbdd=true> 14 | 15 | 16 | 17 | 18 | <#include "partials/head.ftl"> 19 | <#if offline> 20 | <#else> 21 | 22 | 23 |
    24 |
    25 | <#include "partials/navbar.ftl"> 26 | <#include "partials/sidenav.ftl"> 27 |
    28 |
    29 | <#include "partials/test.ftl"> 30 |
    31 |
    32 |
    33 |
    34 | <#include "partials/scripts.ftl"> 35 | 36 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/ExtentTestLogHierarchyTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Test; 5 | 6 | public class ExtentTestLogHierarchyTest { 7 | private ExtentTest test() { 8 | return new ExtentReports().createTest("Test"); 9 | } 10 | 11 | @Test 12 | public void overall() { 13 | ExtentTest test = test(); 14 | test.pass("Pass"); 15 | test.fail("Fail"); 16 | test.info("Info"); 17 | test.skip("Skip"); 18 | test.warning("Warning"); 19 | Assert.assertEquals(test.getStatus(), Status.FAIL); 20 | } 21 | 22 | @Test 23 | public void info() { 24 | ExtentTest test = test(); 25 | test.info("Info"); 26 | Assert.assertEquals(test.getStatus(), Status.PASS); 27 | } 28 | 29 | @Test 30 | public void passed() { 31 | ExtentTest test = test(); 32 | test.pass("Pass"); 33 | test.info("Info"); 34 | Assert.assertEquals(test.getStatus(), Status.PASS); 35 | } 36 | 37 | @Test 38 | public void skipped() { 39 | ExtentTest test = test(); 40 | test.pass("Pass"); 41 | test.info("Info"); 42 | test.skip("Skip"); 43 | Assert.assertEquals(test.getStatus(), Status.SKIP); 44 | } 45 | 46 | @Test 47 | public void warning() { 48 | ExtentTest test = test(); 49 | test.pass("Pass"); 50 | test.info("Info"); 51 | test.skip("Skip"); 52 | test.warning("Warning"); 53 | Assert.assertEquals(test.getStatus(), Status.WARNING); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/NaturalConfTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | import java.util.Calendar; 4 | import java.util.Date; 5 | 6 | import org.testng.Assert; 7 | import org.testng.annotations.Test; 8 | 9 | public class NaturalConfTest { 10 | @Test 11 | public void useNaturalConfReport() throws InterruptedException { 12 | ExtentReports extent = new ExtentReports(); 13 | extent.setReportUsesManualConfiguration(true); 14 | ExtentTest test = extent.createTest("Test").pass("init"); 15 | Thread.sleep(500); 16 | test.pass("complete"); 17 | // must flush to determine time for report 18 | extent.flush(); 19 | Assert.assertTrue(extent.getReport().timeTaken() < 5); 20 | } 21 | 22 | @Test 23 | public void useNaturalConfReportWithTimeChanged() throws InterruptedException { 24 | ExtentReports extent = new ExtentReports(); 25 | extent.setReportUsesManualConfiguration(true); 26 | ExtentTest test = extent.createTest("Test").pass("init"); 27 | test.getModel().setEndTime(new Date(Calendar.getInstance().getTime().getTime() + 5000)); 28 | test.pass("complete"); 29 | // must flush to determine time for report 30 | extent.flush(); 31 | Assert.assertTrue(extent.getReport().timeTaken() >= 5000); 32 | } 33 | 34 | @Test 35 | public void useNaturalConfTest() throws InterruptedException { 36 | ExtentReports extent = new ExtentReports(); 37 | extent.setReportUsesManualConfiguration(true); 38 | ExtentTest test = extent.createTest("Test").pass("init"); 39 | Thread.sleep(500); 40 | test.pass("complete"); 41 | Assert.assertTrue(test.getModel().timeTaken() < 5); 42 | } 43 | 44 | @Test 45 | public void useNaturalConfTestWithTimeChanged() throws InterruptedException { 46 | ExtentReports extent = new ExtentReports(); 47 | extent.setReportUsesManualConfiguration(true); 48 | ExtentTest test = extent.createTest("Test").pass("init"); 49 | test.getModel().setEndTime(new Date(Calendar.getInstance().getTime().getTime() + 5000)); 50 | test.pass("complete"); 51 | Assert.assertTrue(test.getModel().timeTaken() >= 5000); 52 | } 53 | 54 | @Test 55 | public void useNaturalConfTestWithNodes() throws InterruptedException { 56 | ExtentReports extent = new ExtentReports(); 57 | extent.setReportUsesManualConfiguration(true); 58 | ExtentTest test = extent.createTest("Test"); 59 | ExtentTest child = test.createNode("Node").pass("init"); 60 | Thread.sleep(500); 61 | child.pass("complete"); 62 | Assert.assertTrue(test.getModel().timeTaken() < 5); 63 | Assert.assertTrue(child.getModel().timeTaken() < 5); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/ObserverTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | public class ObserverTest { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/ParallelTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | import org.testng.annotations.Test; 6 | 7 | import com.aventstack.extentreports.reporter.ExtentSparkReporter; 8 | 9 | public class ParallelTest { 10 | @Test 11 | public void parallelTests() { 12 | ExtentReports extent = new ExtentReports(); 13 | IntStream.range(0, 10000).parallel().forEach(x -> extent.createTest("Test").info(String.valueOf(x))); 14 | } 15 | 16 | @Test 17 | public void parallelTestsWithReporter() { 18 | ExtentReports extent = new ExtentReports(); 19 | extent.attachReporter(new ExtentSparkReporter("")); 20 | IntStream.range(0, 10000).parallel().forEach(x -> extent.createTest("Test").info(String.valueOf(x))); 21 | } 22 | 23 | @Test 24 | public void parallelLogs() { 25 | ExtentReports extent = new ExtentReports(); 26 | ExtentTest test = extent.createTest("Test"); 27 | IntStream.range(0, 10000).parallel().forEach(x -> test.info(String.valueOf(x))); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/TestIdsTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | import java.util.stream.IntStream; 7 | 8 | import org.testng.Assert; 9 | import org.testng.annotations.Test; 10 | 11 | public class TestIdsTest { 12 | private final int ATTEMPTS = 100; 13 | 14 | @Test 15 | public void verifyAllStartedTestsHaveUniqueIds(Method method) { 16 | ExtentReports extent = new ExtentReports(); 17 | Set set = new HashSet<>(); 18 | // create [times] tests to ensure test-id is not duplicate 19 | IntStream.range(0, ATTEMPTS) 20 | .forEach(x -> set.add(extent.createTest("" + x).info("" + x).getModel().getId())); 21 | Assert.assertEquals(set.size(), ATTEMPTS); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/config/ConfigStoreTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.config; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Test; 5 | 6 | public class ConfigStoreTest { 7 | private ConfigStore store = new ConfigStore(); 8 | 9 | @Test 10 | public void duplicateConfig() { 11 | store.addConfig("config", "value1"); 12 | Assert.assertEquals(store.getConfig("config"), "value1"); 13 | store.addConfig("config", "value2"); 14 | Assert.assertEquals(store.getConfig("config"), "value2"); 15 | } 16 | 17 | @Test 18 | public void containsConfig() { 19 | store.addConfig("config", "value1"); 20 | Assert.assertTrue(store.containsConfig("config")); 21 | Assert.assertFalse(store.containsConfig("config2")); 22 | } 23 | 24 | @Test 25 | public void removeConfig() { 26 | store.addConfig("config", "value1"); 27 | Assert.assertTrue(store.containsConfig("config")); 28 | store.removeConfig("config"); 29 | Assert.assertFalse(store.containsConfig("config")); 30 | } 31 | 32 | @Test 33 | public void configValueTest() { 34 | store.addConfig("c", "v"); 35 | store.addConfig("k", "z"); 36 | Assert.assertTrue(store.getConfig("c").equals("v")); 37 | Assert.assertTrue(store.getConfig("k").equals("z")); 38 | } 39 | 40 | @Test 41 | public void extendConfigWithStore() { 42 | ConfigStore store1 = new ConfigStore(); 43 | store1.addConfig("config1", "value1"); 44 | ConfigStore store2 = new ConfigStore(); 45 | store2.addConfig("config2", "value2"); 46 | store1.extendConfig(store2); 47 | Assert.assertTrue(store1.containsConfig("config1")); 48 | Assert.assertTrue(store1.containsConfig("config2")); 49 | Assert.assertTrue(store2.containsConfig("config2")); 50 | Assert.assertFalse(store2.containsConfig("config1")); 51 | } 52 | 53 | @Test 54 | public void extendConfigWithMap() { 55 | ConfigStore store1 = new ConfigStore(); 56 | store1.addConfig("config1", "value1"); 57 | ConfigStore store2 = new ConfigStore(); 58 | store2.addConfig("config2", "value2"); 59 | store1.extendConfig(store2.getStore()); 60 | Assert.assertTrue(store1.containsConfig("config1")); 61 | Assert.assertTrue(store1.containsConfig("config2")); 62 | Assert.assertTrue(store2.containsConfig("config2")); 63 | Assert.assertFalse(store2.containsConfig("config1")); 64 | } 65 | 66 | @Test 67 | public void configEmpty() { 68 | ConfigStore store = new ConfigStore(); 69 | Assert.assertTrue(store.isEmpty()); 70 | store.addConfig("config1", "value1"); 71 | Assert.assertFalse(store.isEmpty()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/config/external/JsonConfigLoaderTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.config.external; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | 6 | import org.testng.Assert; 7 | import org.testng.annotations.Test; 8 | 9 | import com.aventstack.extentreports.reporter.configuration.ExtentSparkReporterConfig; 10 | import com.aventstack.extentreports.reporter.configuration.Protocol; 11 | import com.aventstack.extentreports.reporter.configuration.Theme; 12 | 13 | public class JsonConfigLoaderTest { 14 | private static final String JSON_FILE = "src/test/resources/config/spark-config.json"; 15 | private static final String JSON_FILE_ENUM = "src/test/resources/config/spark-config_lowercase_enum.json"; 16 | 17 | @Test 18 | public void jsonConfigTest() throws FileNotFoundException { 19 | ExtentSparkReporterConfig conf = ExtentSparkReporterConfig.builder().build(); 20 | JsonConfigLoader loader = new JsonConfigLoader(conf, 21 | new File(JSON_FILE)); 22 | loader.apply(); 23 | Assert.assertEquals(conf.getCss(), "css1"); 24 | Assert.assertEquals(conf.getDocumentTitle(), "Test1"); 25 | Assert.assertEquals(conf.getEncoding(), "utf-16"); 26 | Assert.assertEquals(conf.getReportName(), "Test2"); 27 | Assert.assertEquals(conf.getTimeStampFormat(), "MMM dd, yyyy HH:mm:ss a"); 28 | Assert.assertEquals(conf.getOfflineMode().booleanValue(), true); 29 | Assert.assertEquals(conf.getProtocol(), Protocol.HTTP); 30 | Assert.assertEquals(conf.getTheme(), Theme.DARK); 31 | } 32 | 33 | @Test 34 | public void jsonConfigLowerCaseEnumTest() throws FileNotFoundException { 35 | ExtentSparkReporterConfig conf = ExtentSparkReporterConfig.builder().build(); 36 | JsonConfigLoader loader = new JsonConfigLoader(conf, 37 | new File(JSON_FILE_ENUM)); 38 | loader.apply(); 39 | Assert.assertEquals(conf.getProtocol(), Protocol.HTTP); 40 | Assert.assertEquals(conf.getTheme(), Theme.DARK); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/config/external/XmlConfigLoaderTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.config.external; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | 6 | import org.testng.Assert; 7 | import org.testng.annotations.Test; 8 | 9 | import com.aventstack.extentreports.reporter.configuration.ExtentSparkReporterConfig; 10 | import com.aventstack.extentreports.reporter.configuration.Protocol; 11 | import com.aventstack.extentreports.reporter.configuration.Theme; 12 | 13 | public class XmlConfigLoaderTest { 14 | private static final String XML_FILE = "src/test/resources/config/spark-config.xml"; 15 | private static final String XML_FILE_ENUM = "src/test/resources/config/spark-config.xml"; 16 | 17 | @Test 18 | public void xmlConfigTest() throws FileNotFoundException { 19 | ExtentSparkReporterConfig conf = ExtentSparkReporterConfig.builder().build(); 20 | XmlConfigLoader loader = new XmlConfigLoader(conf, 21 | new File(XML_FILE)); 22 | loader.apply(); 23 | Assert.assertEquals(conf.getCss(), "css1"); 24 | Assert.assertEquals(conf.getDocumentTitle(), "Test1"); 25 | Assert.assertEquals(conf.getEncoding(), "utf-16"); 26 | Assert.assertEquals(conf.getReportName(), "Test2"); 27 | Assert.assertEquals(conf.getTimeStampFormat(), "MMM dd, yyyy HH:mm:ss a"); 28 | Assert.assertEquals(conf.getOfflineMode().booleanValue(), true); 29 | Assert.assertEquals(conf.getProtocol(), Protocol.HTTP); 30 | Assert.assertEquals(conf.getTheme(), Theme.DARK); 31 | } 32 | 33 | @Test 34 | public void xmlConfigLowerCaseEnumTest() throws FileNotFoundException { 35 | ExtentSparkReporterConfig conf = ExtentSparkReporterConfig.builder().build(); 36 | XmlConfigLoader loader = new XmlConfigLoader(conf, 37 | new File(XML_FILE_ENUM)); 38 | loader.apply(); 39 | Assert.assertEquals(conf.getProtocol(), Protocol.HTTP); 40 | Assert.assertEquals(conf.getTheme(), Theme.DARK); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/entity/AuthorEntityTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.entity; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Test; 5 | 6 | import com.aventstack.extentreports.model.Author; 7 | 8 | public class AuthorEntityTest { 9 | 10 | @Test 11 | public void authorName() { 12 | final String name = "Anshoo"; 13 | Author author = new Author(name); 14 | Assert.assertEquals(author.getName(), name); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/entity/CategoryEntityTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.entity; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Test; 5 | 6 | import com.aventstack.extentreports.model.Category; 7 | 8 | public class CategoryEntityTest { 9 | 10 | @Test 11 | public void tagName() { 12 | final String name = "TagName"; 13 | Category tag = new Category(name); 14 | Assert.assertEquals(tag.getName(), name); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/entity/DeviceEntityTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.entity; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Test; 5 | 6 | import com.aventstack.extentreports.model.Device; 7 | 8 | public class DeviceEntityTest { 9 | 10 | @Test 11 | public void deviceName() { 12 | final String name = "DeviceName"; 13 | Device author = new Device(name); 14 | Assert.assertEquals(author.getName(), name); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/entity/LogEntityTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.entity; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Test; 5 | 6 | import com.aventstack.extentreports.Status; 7 | import com.aventstack.extentreports.model.Log; 8 | import com.aventstack.extentreports.model.Media; 9 | import com.aventstack.extentreports.model.ScreenCapture; 10 | 11 | public class LogEntityTest { 12 | 13 | @Test 14 | public void defaultStatusBuilder() { 15 | Log log = Log.builder().build(); 16 | Assert.assertEquals(log.getStatus(), Status.PASS); 17 | } 18 | 19 | /* 20 | * Lombok @Builder.Default bug causing not setting fields on instantiating 21 | * via new 22 | */ 23 | // @Test 24 | // public void defaultStatusInstantiate() { 25 | // Log log = new Log(); 26 | // Assert.assertEquals(log.getStatus(), Status.PASS); 27 | // } 28 | 29 | @Test 30 | public void changedStatus() { 31 | Log log = new Log(); 32 | log.setStatus(Status.FAIL); 33 | Assert.assertEquals(log.getStatus(), Status.FAIL); 34 | log.setStatus(Status.PASS); 35 | Assert.assertEquals(log.getStatus(), Status.PASS); 36 | } 37 | 38 | @Test 39 | public void timestampNonNullOnInit() { 40 | Log log = Log.builder().build(); 41 | Assert.assertNotNull(log.getTimestamp()); 42 | } 43 | 44 | @Test 45 | public void detailsNullOnInit() { 46 | Log log = Log.builder().build(); 47 | Assert.assertNull(log.getDetails()); 48 | } 49 | 50 | @Test 51 | public void seqNegOnInit() { 52 | Log log = Log.builder().build(); 53 | Assert.assertEquals(log.getSeq().intValue(), -1); 54 | } 55 | 56 | @Test 57 | public void mediaEmptyOnInit() { 58 | Log log = Log.builder().build(); 59 | Assert.assertEquals(log.getMedia(), null); 60 | } 61 | 62 | @Test 63 | public void exceptionsEmptyOnInit() { 64 | Log log = Log.builder().build(); 65 | Assert.assertEquals(log.getException(), null); 66 | } 67 | 68 | @Test 69 | public void addMediaDefault() { 70 | Log log = Log.builder().build(); 71 | Assert.assertFalse(log.hasMedia()); 72 | } 73 | 74 | @Test 75 | public void addMediaWithPathToLog() { 76 | Media m = ScreenCapture.builder().path("./img.png").build(); 77 | Log log = Log.builder().media(m).build(); 78 | Assert.assertTrue(log.hasMedia()); 79 | } 80 | 81 | @Test 82 | public void addMediaWithResolvedPathToLog() { 83 | Media m = ScreenCapture.builder().resolvedPath("./img.png").build(); 84 | Log log = Log.builder().media(m).build(); 85 | Assert.assertTrue(log.hasMedia()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/entity/ScreenCaptureTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.entity; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Test; 5 | 6 | import com.aventstack.extentreports.model.ScreenCapture; 7 | 8 | public class ScreenCaptureTest { 9 | 10 | @Test 11 | public void initWithAllEntitiesNull() { 12 | ScreenCapture capture = ScreenCapture.builder().build(); 13 | Assert.assertNull(capture.getBase64()); 14 | Assert.assertNull(capture.getPath()); 15 | Assert.assertNull(capture.getResolvedPath()); 16 | Assert.assertNull(capture.getTitle()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/entity/StatusEntityTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.entity; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import org.testng.Assert; 8 | import org.testng.annotations.Test; 9 | 10 | import com.aventstack.extentreports.Status; 11 | 12 | public class StatusEntityTest { 13 | 14 | private List randomHierarchy() { 15 | List list = Arrays.asList(Status.values()); 16 | Collections.shuffle(list); 17 | return list; 18 | } 19 | 20 | @Test 21 | public void statusMax() { 22 | Assert.assertEquals(Status.max(randomHierarchy()), Status.FAIL); 23 | } 24 | 25 | @Test 26 | public void statusMin() { 27 | Assert.assertEquals(Status.min(randomHierarchy()), Status.INFO); 28 | } 29 | 30 | @Test 31 | public void statusHierarchy() { 32 | List list = Status.getResolvedHierarchy(randomHierarchy()); 33 | Assert.assertTrue(list.get(0).equals(Status.INFO)); 34 | Assert.assertTrue(list.get(Status.values().length - 1).equals(Status.FAIL)); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/entity/TestEntityInitTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.entity; 2 | 3 | import java.util.Collections; 4 | 5 | import org.testng.Assert; 6 | 7 | import com.aventstack.extentreports.Status; 8 | import com.aventstack.extentreports.model.Test; 9 | 10 | public class TestEntityInitTest { 11 | 12 | @org.testng.annotations.Test 13 | public void startAndEndTimesNonNullAtInit() { 14 | Test test = Test.builder().build(); 15 | Assert.assertNotNull(test.getStartTime()); 16 | Assert.assertNotNull(test.getEndTime()); 17 | } 18 | 19 | @org.testng.annotations.Test 20 | public void startIsPassOnInit() { 21 | Test test = Test.builder().build(); 22 | Assert.assertEquals(test.getStatus(), Status.PASS); 23 | } 24 | 25 | @org.testng.annotations.Test 26 | public void levelIs0OnInit() { 27 | Test test = Test.builder().build(); 28 | Assert.assertEquals(test.getLevel().intValue(), 0); 29 | } 30 | 31 | @org.testng.annotations.Test 32 | public void testIsLeafOnInit() { 33 | Test test = Test.builder().build(); 34 | Assert.assertEquals(test.isLeaf(), true); 35 | } 36 | 37 | @org.testng.annotations.Test 38 | public void childrenEmptyOnInit() { 39 | Test test = Test.builder().build(); 40 | Assert.assertEquals(test.getChildren(), Collections.EMPTY_LIST); 41 | } 42 | 43 | @org.testng.annotations.Test 44 | public void logsEmptyOnInit() { 45 | Test test = Test.builder().build(); 46 | Assert.assertEquals(test.getLogs(), Collections.EMPTY_LIST); 47 | } 48 | 49 | @org.testng.annotations.Test 50 | public void authorsEmptyOnInit() { 51 | Test test = Test.builder().build(); 52 | Assert.assertEquals(test.getAuthorSet(), Collections.EMPTY_SET); 53 | } 54 | 55 | @org.testng.annotations.Test 56 | public void devicesEmptyOnInit() { 57 | Test test = Test.builder().build(); 58 | Assert.assertEquals(test.getDeviceSet(), Collections.EMPTY_SET); 59 | } 60 | 61 | @org.testng.annotations.Test 62 | public void tagEmptyOnInit() { 63 | Test test = Test.builder().build(); 64 | Assert.assertEquals(test.getCategorySet(), Collections.EMPTY_SET); 65 | } 66 | 67 | @org.testng.annotations.Test 68 | public void testId1OrGreaterOnInit() { 69 | Test test = Test.builder().build(); 70 | Assert.assertNotEquals(test.getId(), 0); 71 | } 72 | 73 | @org.testng.annotations.Test 74 | public void descriptionNullOnInit() { 75 | Test test = Test.builder().build(); 76 | Assert.assertNull(test.getDescription()); 77 | } 78 | 79 | @org.testng.annotations.Test 80 | public void parentNullOnInit() { 81 | Test test = Test.builder().build(); 82 | Assert.assertNull(test.getParent()); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/entity/service/ExceptionInfoServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.entity.service; 2 | 3 | import org.testng.Assert; 4 | 5 | import com.aventstack.extentreports.model.ExceptionInfo; 6 | import com.aventstack.extentreports.model.service.ExceptionInfoService; 7 | 8 | public class ExceptionInfoServiceTest { 9 | @org.testng.annotations.Test 10 | public void exceptionInfo() { 11 | RuntimeException ex = new RuntimeException("ERROR"); 12 | ExceptionInfo info = ExceptionInfoService.createExceptionInfo(ex); 13 | Assert.assertEquals(info.getException(), ex); 14 | Assert.assertEquals(info.getName(), "java.lang.RuntimeException"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/markuputils/CodeBlockMarkupTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Test; 5 | 6 | public class CodeBlockMarkupTest { 7 | 8 | @Test 9 | public void nullCodeBlockContent() { 10 | Markup m = MarkupHelper.createCodeBlock(null); 11 | Assert.assertEquals(m.getMarkup(), ""); 12 | } 13 | 14 | @Test 15 | public void xmlCodeBlock() { 16 | String xml = "value"; 17 | Markup m = MarkupHelper.createCodeBlock(xml); 18 | Assert.assertTrue(m.getMarkup().contains(xml)); 19 | } 20 | 21 | @Test 22 | public void xmlCodeBlockWithLang() { 23 | String xml = "value"; 24 | Markup m = MarkupHelper.createCodeBlock(xml, CodeLanguage.XML); 25 | Assert.assertTrue(m.getMarkup().contains(xml)); 26 | } 27 | 28 | @Test 29 | public void jsonCodeBlock() { 30 | String json = "{ 'key': 'value' }"; 31 | Markup m = MarkupHelper.createCodeBlock(json); 32 | Assert.assertTrue(m.getMarkup().contains(json)); 33 | } 34 | 35 | @Test(priority = 1) 36 | public void jsonCodeBlockWithLang() { 37 | String json = "{ 'key': 'value' }"; 38 | Markup m = MarkupHelper.createCodeBlock(json, CodeLanguage.JSON); 39 | Assert.assertTrue(m.getMarkup().contains(json)); 40 | Assert.assertTrue(m.getMarkup().contains("jsonTreeCreate")); 41 | Assert.assertTrue(m.getMarkup().contains("")); 43 | } 44 | 45 | @Test(priority = 2) 46 | public void jsonCodeBlockWithLangMultiple() { 47 | String json = "{ 'key': 'value' }"; 48 | Markup m = MarkupHelper.createCodeBlock(json, CodeLanguage.JSON); 49 | Assert.assertTrue(m.getMarkup().contains(json)); 50 | Assert.assertTrue(m.getMarkup().contains("jsonTreeCreate")); 51 | Assert.assertTrue(m.getMarkup().contains("")); 53 | m = MarkupHelper.createCodeBlock(json, CodeLanguage.JSON); 54 | Assert.assertTrue(m.getMarkup().contains(json)); 55 | Assert.assertTrue(m.getMarkup().contains("jsonTreeCreate")); 56 | Assert.assertTrue(m.getMarkup().contains("")); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/markuputils/Foo.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import com.aventstack.extentreports.annotations.MarkupIgnore; 9 | 10 | public class Foo { 11 | public List names = Arrays.asList("Anshoo", "Extent", "Klov"); 12 | @SuppressWarnings("unused") 13 | private Object[] stack1 = new Object[]{"Java", "C#", "Angular"}; 14 | @MarkupIgnore 15 | private List ignored = Arrays.asList("Anshoo/Ignore", "Extent/Ignore", "Klov/Ignore"); 16 | @SuppressWarnings({"serial", "unused"}) 17 | private Map items = new HashMap() { 18 | { 19 | put("Item1", "Value1"); 20 | put("Item2", "Value2"); 21 | put("Item3", "Value3"); 22 | } 23 | }; 24 | } -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/markuputils/LabelMarkupTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.markuputils; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Test; 5 | 6 | public class LabelMarkupTest { 7 | 8 | @Test 9 | public void labelWithNullText() { 10 | Markup m = MarkupHelper.createLabel(null, ExtentColor.TRANSPARENT); 11 | Assert.assertEquals(m.getMarkup(), ""); 12 | } 13 | 14 | @Test 15 | public void labelWithEmptyText() { 16 | Markup m = MarkupHelper.createLabel("", ExtentColor.TRANSPARENT); 17 | Assert.assertEquals(m.getMarkup(), ""); 18 | } 19 | 20 | @Test 21 | public void labelWithText() { 22 | String text = "Extent"; 23 | Markup m = MarkupHelper.createLabel(text, ExtentColor.TRANSPARENT); 24 | Assert.assertTrue(m.getMarkup().contains(text)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/aventstack/extentreports/observer/ReportEntityObserverTest.java: -------------------------------------------------------------------------------- 1 | package com.aventstack.extentreports.observer; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Test; 5 | 6 | import com.aventstack.extentreports.ExtentReports; 7 | import com.aventstack.extentreports.observer.entity.ReportEntity; 8 | 9 | import io.reactivex.rxjava3.core.Observer; 10 | import io.reactivex.rxjava3.disposables.Disposable; 11 | 12 | public class ReportEntityObserverTest { 13 | private Disposable disp; 14 | private ReportEntity entity; 15 | 16 | @Test 17 | public void disposableNonNull() { 18 | ExtentReports extent = new ExtentReports(); 19 | Assert.assertNull(disp); 20 | Assert.assertNull(entity); 21 | extent.attachReporter(new TestReporter()); 22 | Assert.assertNotNull(disp); 23 | Assert.assertNull(entity); 24 | extent.flush(); 25 | Assert.assertNotNull(disp); 26 | Assert.assertNotNull(entity); 27 | } 28 | 29 | @SuppressWarnings("rawtypes") 30 | private class TestReporter implements ReportObserver { 31 | @Override 32 | public Observer getReportObserver() { 33 | return new Observer() { 34 | @Override 35 | public void onSubscribe(Disposable d) { 36 | disp = d; 37 | } 38 | 39 | @Override 40 | public void onNext(ReportEntity value) { 41 | entity = value; 42 | } 43 | 44 | @Override 45 | public void onError(Throwable e) { 46 | } 47 | 48 | @Override 49 | public void onComplete() { 50 | } 51 | }; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/resources/config/spark-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "theme": "DARK", 3 | "encoding": "utf-16", 4 | "protocol": "HTTP", 5 | "timelineEnabled": true, 6 | "offlineMode": true, 7 | "documentTitle": "Test1", 8 | "reportName": "Test2", 9 | "timeStampFormat": "MMM dd, yyyy HH:mm:ss a", 10 | "js": "js1", 11 | "css": "css1" 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/config/spark-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DARK 8 | 9 | 10 | 11 | utf-16 12 | 13 | 14 | 15 | 16 | HTTP 17 | 18 | 19 | true 20 | 21 | 22 | true 23 | 24 | 25 | Test1 26 | 27 | 28 | Test2 29 | 30 | 31 | MMM dd, yyyy HH:mm:ss a 32 | 33 | 34 | js1 35 | 36 | 37 | css1 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/test/resources/config/spark-config_lowercase_enum.json: -------------------------------------------------------------------------------- 1 | { 2 | "theme": "dark", 3 | "encoding": "utf-16", 4 | "protocol": "http", 5 | "timelineEnabled": true, 6 | "offlineMode": true, 7 | "documentTitle": "Test1", 8 | "reportName": "Test2", 9 | "timeStampFormat": "MMM dd, yyyy HH:mm:ss a", 10 | "js": "js1", 11 | "css": "css1" 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/config/spark-config_lowercase_enum.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | dark 8 | 9 | 10 | 11 | utf-16 12 | 13 | 14 | 15 | 16 | http 17 | 18 | 19 | true 20 | 21 | 22 | true 23 | 24 | 25 | Test1 26 | 27 | 28 | Test2 29 | 30 | 31 | MMM dd, yyyy HH:mm:ss a 32 | 33 | 34 | js1 35 | 36 | 37 | css1 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/test/resources/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anshooarora/extentreports-java/925c18aac5e7fe935676822f33803ab0444208e6/src/test/resources/img.png --------------------------------------------------------------------------------