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

org.scalajs.testing.adapter.HTMLRunnerBuilder.scala Maven / Gradle / Ivy

The newest version!
/*
 * Scala.js (https://www.scala-js.org/)
 *
 * Copyright EPFL.
 *
 * Licensed under Apache License 2.0
 * (https://www.apache.org/licenses/LICENSE-2.0).
 *
 * See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 */

package org.scalajs.testing.adapter

import java.io.{File, IOException}
import java.nio.charset.StandardCharsets.UTF_8
import java.nio.file._
import java.nio.file.attribute.BasicFileAttributes

import sbt.testing.{Framework, TaskDef}

import org.scalajs.jsenv.{Input, UnsupportedInputException}
import org.scalajs.jsenv.JSUtils.escapeJS

import org.scalajs.testing.common._

/** Template for the HTML runner. */
object HTMLRunnerBuilder {
  @deprecated("Use write instead", "1.2.0")
  def writeToFile(output: File, title: String, input: Seq[Input],
      frameworkImplClassNames: List[List[String]],
      taskDefs: List[TaskDef]): Unit = {
    val outputPath = output.toPath()
    val artifactsDir =
      Files.createTempDirectory(outputPath.getParent(), ".html-artifacts")

    sys.addShutdownHook {
      Files.walkFileTree(artifactsDir, new SimpleFileVisitor[Path] {
        override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = {
          Files.delete(file)
          FileVisitResult.CONTINUE
        }

        override def postVisitDirectory(dir: Path, exc: IOException): FileVisitResult = {
          Files.delete(dir)
          FileVisitResult.CONTINUE
        }
      })
    }

    write(outputPath, artifactsDir, title, input, frameworkImplClassNames, taskDefs)
  }

  def write(output: Path, artifactsDir: Path, title: String, input: Seq[Input],
      frameworkImplClassNames: List[List[String]],
      taskDefs: List[TaskDef]): Unit = {
    val absoluteArtifacts = artifactsDir.toAbsolutePath()
    val outputDir = output.toAbsolutePath().normalize().getParent()

    try {
      outputDir.relativize(absoluteArtifacts)
    } catch {
      case e: IllegalArgumentException =>
        throw new IllegalArgumentException(
            "cannot relativize `artifactsDir` with respect to `output`", e)
    }

    def artifactPath(name: String): (String, Path) = {
      val path = absoluteArtifacts.resolve(name)
      val relPath = outputDir.relativize(path)
      (joinRelPath(relPath), path)
    }

    def scriptTag(index: Int, tpe: String, content: Path) = {
      val src = {
        try {
          joinRelPath(outputDir.relativize(content))
        } catch {
          case _: IllegalArgumentException =>
            // Cannot relativize this content.
            val (src, target) = artifactPath(f"input$index-${content.getFileName()}")
            Files.copy(content, target, StandardCopyOption.REPLACE_EXISTING)
            src
        }
      }

      s""""""
    }

    val loadJSTags = input.zipWithIndex.map {
      case (Input.Script(script), i)   => scriptTag(i, "text/javascript", script)
      case (Input.ESModule(module), i) => scriptTag(i, "module", module)

      case _ =>
        throw new UnsupportedInputException(
            s"Unsupported input for the generation of an HTML runner: $input")
    }

    val bridgeModeStr = {
      val tests = new IsolatedTestSet(frameworkImplClassNames, taskDefs)
      val mode = TestBridgeMode.HTMLRunner(tests)
      Serializer.serialize[TestBridgeMode](mode)
    }

    val cssHref = {
      val name = "test-runner.css"
      val (href, target) = artifactPath(name)
      val in = getClass.getResourceAsStream(name)
      try Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING)
      finally in.close()
      href
    }

    val htmlContent = s"""
      
      
        
          ${htmlEscaped(title)}
          
          
          
          ${loadJSTags.mkString("\n")}
        
        
      
    """

    Files.write(output, java.util.Arrays.asList(htmlContent), UTF_8)
  }

  private def htmlEscaped(str: String): String = str.flatMap {
    case '<' => "<"
    case '>' => ">"
    case '"' => """
    case '&' => "&"
    case c   => c.toString()
  }

  /* Necessary on Windows to not have backslashes in URIs.
   *
   * .map(_.toString()).mkString("/")
   */
  private def joinRelPath(p: Path): String = {
    require(p.getRoot() == null)

    val partsIter = p.iterator()
    val result = new StringBuilder()
    while (partsIter.hasNext()) {
      result.append(partsIter.next())
      if (partsIter.hasNext())
        result.append('/')
    }

    result.toString()
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy