diff options
Diffstat (limited to 'examples/scala-js/test-bridge/src/main/scala/scala/scalajs/testbridge/internal')
-rw-r--r-- | examples/scala-js/test-bridge/src/main/scala/scala/scalajs/testbridge/internal/ConsoleTestOutput.scala | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/examples/scala-js/test-bridge/src/main/scala/scala/scalajs/testbridge/internal/ConsoleTestOutput.scala b/examples/scala-js/test-bridge/src/main/scala/scala/scalajs/testbridge/internal/ConsoleTestOutput.scala new file mode 100644 index 0000000..c89a32e --- /dev/null +++ b/examples/scala-js/test-bridge/src/main/scala/scala/scalajs/testbridge/internal/ConsoleTestOutput.scala @@ -0,0 +1,118 @@ +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(" ")) + } + +} |