All Downloads are FREE. Search and download functionalities are using the official Maven repository.

clairvoyance.scalatest.export.ScalaTestHtmlFormat.scala Maven / Gradle / Ivy

package clairvoyance.scalatest.export

import clairvoyance.export._
import clairvoyance.rendering.{CustomRendering, Rendering}
import clairvoyance.rendering.Markdown.markdownToXhtml
import clairvoyance.rendering.Reflection.tryToCreateObject
import clairvoyance.scalatest.{SkipInteractions, SkipSpecification, Tags}
import clairvoyance.scalatest.ClairvoyantContext.tagNames
import clairvoyance.state.{TestState, TestStates}
import java.util.UUID
import org.scalatest.events._
import org.scalatest.{Tag, exceptions}
import scala.xml.NodeSeq

case class ScalaTestHtmlFormat (override val xml: NodeSeq = NodeSeq.Empty) extends HtmlFormat(xml) {
  type Self = ScalaTestHtmlFormat

  protected def print(xml2: NodeSeq): Self = ScalaTestHtmlFormat(xml ++ xml2)

  def printSidebar(results: Seq[SuiteResult]): Self = print(sidebar(results))

  private def sidebar(results: Seq[SuiteResult]): NodeSeq = {
    val summarisedSuites = results.map { suite =>
      
  • {suite.suiteName}
      { suite.eventList.flatMap { case event: ScopeOpened => stringToPrintWhenNoError(event.formatter, event.nameInfo.suiteName) match { case Some(text) => Some(
    • {formatShortExampleName(text)}
    • ) case None => NodeSeq.Empty } case event: TestStarting => Some(
    • - {formatShortExampleName(event.testText)}
    • ) case _ => None } }
  • } } private def tableOfContentsFor(suiteResult: SuiteResult): NodeSeq = {
      { suiteResult.eventList.map { case event: TestSucceeded => renderFragmentForTableOfContents(event) case TestFailedOrCancelled(event) => renderFragmentForTableOfContents(event) case TestPendingOrIgnored (event) => renderFragmentForTableOfContents(event) case _ => NodeSeq.Empty } }
    } private def renderFragmentForTableOfContents(event: TestSucceeded): NodeSeq = renderFragmentForTableOfContents(event.testName, event.testText, event.recordedEvents, "test-passed", "test_passed") private def renderFragmentForTableOfContents(event: TestFailedOrCancelled): NodeSeq = renderFragmentForTableOfContents(event.testName, event.testText, event.recordedEvents, "test-failed", event.cssClass) private def renderFragmentForTableOfContents(event: TestPendingOrIgnored): NodeSeq = renderFragmentForTableOfContents(event.testName, event.testText, event.recordedEvents, "test-not-run", event.cssClass) private def renderFragmentForTableOfContents(testName: String, testText: String, recordedEvents: IndexedSeq[RecordableEvent], listCssClass: String, cssClass: String): NodeSeq =
  • {formatShortExampleName(testName)}
  • def printBody(specificationTitle: String, suiteResult: SuiteResult): Self = print(

    {wordify(specificationTitle)}

    {tableOfContentsFor(suiteResult)} { suiteResult.eventList.map { case ScopeOpenedOrPending(event) => renderFragmentForBody(event) case event: TestSucceeded => renderFragmentForBody(event) case TestFailedOrCancelled(event) => renderFragmentForBody(event) case TestPendingOrIgnored(event) => renderFragmentForBody(event) case event: MarkupProvided => renderFragmentForBody(event, "markup") // AlertProvided, InfoProvided, and NoteProvided must not show up in the HTML report case _ => NodeSeq.Empty } }
    ) private def renderFragmentForBody(event: ScopeOpenedOrPending): NodeSeq = stringToPrintWhenNoError(event.formatter, event.nameInfo.suiteName) match { case Some(string) => markdownToXhtml("# " + string) case None => NodeSeq.Empty } private def renderFragmentForBody(event: TestSucceeded): NodeSeq = { val (suiteClassName, testName, testText, duration) = (event.suiteClassName.get, event.testName, event.testText, event.duration) val annotations = annotationsFor(event.suiteName, event.testName) val testState = TestStates.dequeue(testName) val rendering = renderingFor(suiteClassName)
    {markdownToXhtml(s"## $testText")}
    { if (!annotations.contains(SkipSpecification))

    Specification

    {SpecificationFormatter.format(getCodeFrom(suiteClassName, event), Seq.empty, suiteClassName, codeFormatFor(suiteClassName))}
    }

    Execution

    {duration.fold("")(milliseconds => s"Passed in $milliseconds ms")}
    {interestingGivensTable(testState, rendering)} {capturedInputsAndOutputs(testState, rendering, annotations)}
    } private def getCodeFrom(location: String, event: TestSucceeded): List[(Int, String)] = { event.location match { case Some(LineInFile(ln, _)) => FromSource.getCodeFrom(location, ln) case a@_ => FromSource.getCodeFrom(location, event.testText) } } private def renderFragmentForBody(event: TestFailedOrCancelled): NodeSeq = { val annotations = annotationsFor(event.suiteName, event.testName) val testState = TestStates.dequeue(event.testName) val rendering = renderingFor(event.suiteClassName) val linkId = UUID.randomUUID.toString val contentId = UUID.randomUUID.toString val (grayStackTraceElements, blackStackTraceElements) = event.throwable match { case Some(throwable) => val stackTraceElements = throwable.getStackTrace.toList throwable match { case sde: exceptions.StackDepthException => (stackTraceElements.take(sde.failedCodeStackDepth), stackTraceElements.drop(sde.failedCodeStackDepth)) case _ => (List(), stackTraceElements) } case None => (List(), List()) }
    {markdownToXhtml("## " + event.testText)}
    { if (!annotations.contains(SkipSpecification))

    Specification

    {
              val sourceLines = FromSource.getCodeFrom(event.suiteClassName, event.testText)
              SpecificationFormatter.format(sourceLines, event.throwable.get.getStackTrace.toList, event.suiteClassName, codeFormatFor(event.suiteClassName))
              }
    }

    Execution

    { event.duration.fold(NodeSeq.Empty)(milliseconds => {event.name} after {milliseconds} ms
    )}
    > { event.message }
    [ show stacktrace ]
    {interestingGivensTable(testState, rendering)} {capturedInputsAndOutputs(testState, rendering, annotations)}
    } private def capturedInputsAndOutputs(testState: Option[TestState], rendering: Rendering, annotations: Set[Tag]): NodeSeq = {
    {loggedInputsAndOutputs(testState.map(x => x.copy(x.interestingGivens, x.capturedInputsAndOutputs.filterNot(_.key.matches(".*(Graph|Diagram).*")))), rendering)}
    {loggedInputsAndOutputs(testState.map(x => x.copy(x.interestingGivens, x.capturedInputsAndOutputs.filter(_.key.matches(".*(Graph|Diagram).*")))), rendering)}
    } private def renderFragmentForBody(event: TestPendingOrIgnored): NodeSeq = {
    {markdownToXhtml("## " + event.testText)}

    Specification

    {SpecificationFormatter.format(FromSource.getCodeFrom(event.suiteClassName, event.testText), Seq.empty, event.suiteClassName, codeFormatFor(event.suiteClassName))}

    Execution

    {event.name}
    } private def renderFragmentForBody(event: MarkupProvided, cssClass: String): NodeSeq = markdownToXhtml(event.text) private def stringToPrintWhenNoError(formatter: Option[Formatter], suiteName: String): Option[String] = { formatter match { case Some(IndentedText(_, rawText, _)) => Some(rawText) case Some(MotionToSuppress) => None case _ => Some(suiteName) } } private def renderingFor(className: String): Rendering = new Rendering(tryToCreateObject[CustomRendering](className)) private def codeFormatFor(className: String): CodeFormat = tryToCreateObject[CodeFormat](className).getOrElse(DefaultCodeFormat) private def annotationsFor(suiteName: String, testName: String): Set[Tag] = { val tags = tagNames((suiteName, testName)) Tags.declared.filter(t => tags.contains(t.name)) } }




    © 2015 - 2025 Weber Informatics LLC | Privacy Policy