package scala.scalajs.testbridge.internal
import scala.scalajs.js
import scala.scalajs.js.annotation.JSExport
import scala.scalajs.testbridge._
import scala.scalajs.runtime.StackTrace.ColumnStackTraceElement
/** Implementation of TestOutput.
*
* Attention: This class monkey-patches console.log. Make sure it is loaded
* before any output. It also should always be paired with a
* [[scala.scalajs.sbtplugin.testing.TestOutputConsole]] on the JVM side.
*/
@JSExport
protected object ConsoleTestOutput extends TestOutput {
/** monkey-patches console.log when class is loaded */
private val savedConsoleLog: js.Function1[String, Unit] = {
import js.Dynamic.{ global => g }
val console = g.console
val savedLog = console.log
val patch = (new MonkeyPatchConsole).asInstanceOf[js.Dynamic]
// Need to write updateDynamic explicitly here. Since 2.10.x
// chokes on this ("erroneous or inaccessible type")
console.updateDynamic("log")(patch.log.bind(patch))
savedLog.bind(console).asInstanceOf[js.Function1[String, Unit]]
}
type Color = String
val errorColor = "\u001b[31m"
val successColor = "\u001b[32m"
val infoColor = "\u001b[34m"
private val reset = "\u001b[0m"
def color(message: String, color: String): String =
message.split('\n').mkString(color, reset + '\n' + color, reset)
def error(message: String,
stack: Array[StackTraceElement]): Unit = {
sendTrace(stack)
send("error", message)
}
def error(message: String): Unit =
error(message, Array.empty)
def failure(message: String,
stack: Array[StackTraceElement]): Unit = {
sendTrace(stack)
send("failure", message)
}
def failure(message: String): Unit =
failure(message, Array.empty)
def succeeded(message: String): Unit =
send("succeeded", message)
def skipped(message: String): Unit =
send("skipped", message)
def pending(message: String): Unit =
send("pending", message)
def ignored(message: String): Unit =
send("ignored", message)
def canceled(message: String): Unit =
send("canceled", message)
val log =
new TestOutputLog {
def info(message: String): Unit = send("info", message)
def warn(message: String): Unit = send("warn", message)
def error(message: String): Unit = send("error-log", message)
}
private def send(fct: String, msg: String) = {
val escaped = msg
.replace("\\", "\\\\")
.replace("\n", "\\n")
.replace("\r", "\\r")
savedConsoleLog(fct + "|" + escaped)
}
private def sendTrace(stack: Array[StackTraceElement]) = for {
el <- stack
} send("trace", serializeStackElem(el))
private def serializeStackElem(e: StackTraceElement) = {
val flds = List(
e.getClassName,
e.getMethodName,
e.getFileName,
e.getLineNumber.toString,
e.getColumnNumber.toString)
flds.mkString("|")
}
/** used to monkey-patch console (only log will be used)
* we can't write a simple lambda, because we need varargs
*/
private class MonkeyPatchConsole {
@JSExport
def log(msg: js.Any*): Unit = send("console-log", msg.mkString(" "))
}
}