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

org.specs2.reporter.HtmlResultOutput.scala Maven / Gradle / Ivy

package org.specs2
package reporter

import scala.xml._
import control._
import main.{ Arguments, Diffs }
import text.Markdown._
import text._
import io.Paths._
import NotNullStrings._
import text.Trim._
import execute._
import xml.Nodex._
import specification._
import html.Htmlx._

/**
 * This class stores the html to print to a file (as a NodeSeq object)
 * 
 * An instance of that class is immutable so each print method returns another instance
 * containing more xml to print.
 *
 */
private[specs2]
case class HtmlResultOutput(xml: NodeSeq = NodeSeq.Empty, filePath: String = "", textPrinter: String => NodeSeq = toXhtml(_)) extends HtmlReportOutput { outer =>

  /**
   * start of the output
   */
  private[specs2] lazy val blank = new HtmlResultOutput(NodeSeq.Empty, outer.filePath)
  /** set the file path of the file being written */
  def filePathIs(path: String) = copy(filePath = path)
  /** base directory for this file path */
  def baseDir = filePath.baseDir
  /** print the NodeSeq inside the html tags */
  def printHtml(n: =>NodeSeq) = print({n})
  /** print the NodeSeq inside the body tags, with anchors for header tags */
  def printBody(n: =>NodeSeq) = print(({n}).addHeadersAnchors)
  /** print the head of the document */
  def printHead = print(xml ++ head)

  /** print a br tag */
  def printBr                                         = printOkStatus(

) /** print a paragraph for some text */ def printPar(text: String = "") = printOkStatus(

{wiki(text)}

) /** print some text */ def printText(text: String = "", level: Int = 0) = printOkStatus(div(wiki(text), level)) /** print some text in a paragraph */ def printTextPar(text: String = "", level: Int = 0) = printOkStatus(p(wiki(text), level)) /** * print the xhtml for a specification start: * * - the html title is the specification title * - if there are no issues then print a h2 header with the title of the specification * - if there are issues add a toggle link so that only issues can be displayed */ def printSpecStart(name: SpecName, stats: Stats) = { print({name.title}). print { val header = if (stats.hasIssues)

{name.title} {showOnlyShowAllLinks(elementClass = "ok", "(issues only)", "(all)")}

else

{name.title}

header.updateHeadAttribute("specId", name.id) } } /** * print a link * * - if it is a link to another specification: * - if it has issues, set a corresponding icon * - add a subtoc element with the specification id so that the TableOfContents class knows where to insert the sub table content corresponding * to the linked specification when building the global table of contents * * - if this is an arbitrary link, print a normal html link */ def printLink(link: HtmlLink, level: Int, stats: Stats = Stats(), hidden: Boolean = false) = { val linkStatus = if (stats.hasIssues) "ko" else "ok" val htmlLink = outer.copy(xml = NodeSeq.Empty).printLink(link).xml link match { case slink @ SpecHtmlLink(name, before, l, after, tip) => { print(). printStatus(div( ++ t(" ") ++ htmlLink, level, hidden), linkStatus) } case UrlHtmlLink(url, before, l, after, tip) => printStatus(div(htmlLink, level, hidden), linkStatus) } } def printLink(link: HtmlLink) = print(wiki(link.beforeText) ++ {wiki(link.linkText)} ++ wiki(link.afterText)) /** print some text with a status icon (with an ok class) */ def printTextWithIcon(message: MarkupString, iconName: String, level: Int = 0) = printOkStatus(textWithIcon(message, iconName, level)) /** print some xml with a status icon (with an ok class) */ def printOkXmlWithIcon(xml: NodeSeq, iconName: String, level: Int = 0) = printOkStatus(xmlWithIcon(xml, iconName, level)) /** print some xml with a status icon (with an ok class) */ def printKoXmlWithIcon(xml: NodeSeq, iconName: String, level: Int = 0) = printKoStatus(xmlWithIcon(xml, iconName, level)) /** print an issue with a status icon (with a ko class) */ def printIssueWithIcon(message: MarkupString, iconName: String, level: Int = 0) = printKoStatus(textWithIcon(message, iconName, level)) /** print an exception message (with a ko class) */ def printExceptionMessage(e: Result with ResultStackTrace, level: Int) = printKoStatus(div(" "+e.message+" ("+e.location+")", level)) /** * print a collapsible exception message (with a ko class) * * the message in enclosed in a div which has a unique id and associated onclick function to show/hide it */ def printCollapsibleExceptionMessage(e: Result with ResultStackTrace, level: Int) = printKoStatus(div( ++ t(" "+e.message.notNull+" ("+e.location+")"), level)) /** * print the details of a Failure message in a collapsible div */ def printDetailedFailure(details: Details, level: Int, diffs: Diffs) = { details match { case FailureDetails(expected, actual) if diffs.show(expected, actual) => { val (expectedDiff, actualDiff) = diffs.showDiffs(expected, actual) val (expectedMessage, actualMessage) = ("Expected: " + expectedDiff, "Actual: " + actualDiff) val (expectedFull, actualFull) = ("Expected (full): " + expected, "Actual (full): " + actual) printKoStatus(div( ++ t("details"), level) ++ ) } case _ => this } } /** * print a stacktrace for a failure or an exception * * The stacktrace elements are filtered with the traceFilter parameter */ def printStack(e: ResultStackTrace, level: Int, traceFilter: StackTraceFilter) = enclose((t: NodeSeq) => koStatus()) { traceFilter(e.stackTrace).foldLeft(blank) { (res, cur) => res.printText(cur.toString, level) } } /** * print the final statistics for a specification as a table */ def printStats(n: SpecName, stats: Stats) = { val title = "Total for specification" + ((" "+n.name.trim) unless n.name.isEmpty) val classStatus = if (stats.hasIssues) "failure" else "success" print(
{title}
Finished in{stats.time}
Results{ stats.displayResults(Arguments("nocolor")) }
) } /** * print the html for a Form, by just adding the corresponding xml to the current output */ def printForm(form: NodeSeq) = print(form) protected def printOkStatus(n: NodeSeq) = print(okStatus(n)) protected def printKoStatus(n: NodeSeq) = print(koStatus(n)) protected def printStatus(n: NodeSeq, st: String) = print(status(n, st)) protected def textWithIcon(message: MarkupString, iconName: String, level: Int = 0) = div( ++ t(" ") ++ wiki(message.toHtml), level) protected def xmlWithIcon(xml: NodeSeq, iconName: String, level: Int = 0) = div(
{xml}
, level) protected def icon(t: String) = baseDir+"images/icon_"+t+"_sml.gif" protected def okStatus(n: NodeSeq) = status(n, "ok") protected def koStatus(n: NodeSeq) = status(n, "ko") /** print a NodeSeq with a given status class */ protected def status(n: NodeSeq, st: String) = {n} /** create a div around some markup text to be displayed at a certain level of identation */ protected def div(string: String, level: Int): NodeSeq = div(t(string), level) /** create a div around a NodeSeq to be displayed at a certain level of identation */ protected def div(n: NodeSeq, level: Int, hidden: Boolean = false): NodeSeq =
{n}
/** create a paragraph around a NodeSeq to be displayed at a certain level of identation */ protected def p(n: NodeSeq, level: Int) =

{n}

/** create a Text node */ protected def t(text: String): NodeSeq = scala.xml.Text(text) protected def toggleElement(a: Any) = "toggleImage(this); showHide('"+id(a)+"')" protected def id(a: Any) = System.identityHashCode(a).toString /** render some markup text as xhtml */ protected def wiki(text: String) = textPrinter(text) /** * Head of the html document. It contains: * * - links to the prettify css and javascript functions to render code * - jquery scripts to render the table of contents as a tree * - tabber css and scripts to display tabs * - show and hide functions */ def head = /** * define custom javascript functions to manipulate elements on the page, mostly to show and hide elements */ def javascript = /** * Usage: out.enclose((t: NodeSeq) => {t})(
inside
)) * * to create
inside
) * * @return some xml (rest) enclosed in another block */ private def enclose(f: NodeSeq => NodeSeq)(rest: =>HtmlResultOutput): HtmlResultOutput = print(f(rest.xml)) def print(xml2: NodeSeq): HtmlResultOutput = copy(xml = xml ++ xml2) def print(xml2: Elem): HtmlResultOutput = copy(xml = xml ++ xml2) /** * @param elementClass class of elements to show/hide * @param showOnlyLabel label to display for the elements to show only * @param showAllLabel label to display for showing all the elements * * @return 2 links allowing to show/hide some elements on a html page */ protected def showOnlyShowAllLinks(elementClass: String, showOnlyLabel: String, showAllLabel: String): NodeSeq = { val (showOnlyId, showAllId) = ("onlyIssuesLink", "allElementsLink") val showOnlyOnclick = "hideByClass('"+elementClass+"');hideById('"+showOnlyId+"');showById('"+showAllId+"')" val showAllOnclick = "showByClass('"+elementClass+"');hideById('"+showAllId+"');showById('"+showOnlyId+"')" {showOnlyLabel} ++ } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy