From 4b3d2ec7ae4f0187f9806f71ebcb5066a4801766 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Fri, 7 Jul 2023 18:11:01 +0200 Subject: [PATCH] bugfix: Don't try to discover test frameworks if none exist Previously, even if node_modules wouldn't exist we would run test discovery, which requires the node_modules and the scripts it contains. Now, we show an error in such a case. This seems to have hanged the node process causing no tests to be discovered. I am not sure how to properly test it yet, but I need to dig into the JS part at some point since from earlier discussions with Sebastien the bridges might be problematic. --- .../main/scala/bloop/scalajs/JsBridge.scala | 45 +++++++++++-------- .../scala/bloop/scalajs/jsenv/NodeJsEnv.scala | 6 ++- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala b/bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala index 2846bc3e05..86877f94d5 100644 --- a/bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala +++ b/bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala @@ -147,25 +147,32 @@ object JsBridge { env: Map[String, String] ): (List[sbt.testing.Framework], () => Unit) = { implicit val debugFilter: DebugFilter = DebugFilter.Test - val nodeModules = baseDirectory.resolve("node_modules").toString - logger.debug("Node.js module path: " + nodeModules) - val fullEnv = Map("NODE_PATH" -> nodeModules) ++ env - val config = - NodeJSConfig().withExecutable(nodePath).withCwd(Some(baseDirectory)).withEnv(fullEnv) - val nodeEnv = - if (!jsConfig.jsdom.contains(true)) new NodeJSEnv(logger, config) - else new JsDomNodeJsEnv(logger, config) - - // The order of the scripts mandates the load order in the JavaScript runtime - val input = jsConfig.kind match { - case ModuleKindJS.NoModule => Input.Script(jsPath) - case ModuleKindJS.CommonJSModule => Input.CommonJSModule(jsPath) - case ModuleKindJS.ESModule => Input.ESModule(jsPath) - } + val nodeModules = baseDirectory.resolve("node_modules") + if (nodeModules.toFile().exists()) { + logger.debug("Node.js module path: " + nodeModules.toString()) + val fullEnv = Map("NODE_PATH" -> nodeModules.toString()) ++ env + val config = + NodeJSConfig().withExecutable(nodePath).withCwd(Some(baseDirectory)).withEnv(fullEnv) + val nodeEnv = + if (!jsConfig.jsdom.contains(true)) new NodeJSEnv(logger, config) + else new JsDomNodeJsEnv(logger, config) + + // The order of the scripts mandates the load order in the JavaScript runtime + val input = jsConfig.kind match { + case ModuleKindJS.NoModule => Input.Script(jsPath) + case ModuleKindJS.CommonJSModule => Input.CommonJSModule(jsPath) + case ModuleKindJS.ESModule => Input.ESModule(jsPath) + } - val testConfig = TestAdapter.Config().withLogger(new Logger(logger)) - val adapter = new TestAdapter(nodeEnv, Seq(input), testConfig) - val result = adapter.loadFrameworks(frameworkNames).flatMap(_.toList) - (result, () => adapter.close()) + val testConfig = TestAdapter.Config().withLogger(new Logger(logger)) + val adapter = new TestAdapter(nodeEnv, Seq(input), testConfig) + val result = adapter.loadFrameworks(frameworkNames).flatMap(_.toList) + (result, () => adapter.close()) + } else { + logger.error( + s"Cannot discover test frameworks, missing node_modules in test project, expected them at $nodeModules" + ) + (Nil, () => ()) + } } } diff --git a/bridges/scalajs-1/src/main/scala/bloop/scalajs/jsenv/NodeJsEnv.scala b/bridges/scalajs-1/src/main/scala/bloop/scalajs/jsenv/NodeJsEnv.scala index 95ccb13bc3..82e9a7a983 100644 --- a/bridges/scalajs-1/src/main/scala/bloop/scalajs/jsenv/NodeJsEnv.scala +++ b/bridges/scalajs-1/src/main/scala/bloop/scalajs/jsenv/NodeJsEnv.scala @@ -124,6 +124,7 @@ final class NodeJSEnv(logger: Logger, config: NodeJSConfig) extends JSEnv { } private def internalStart(input: Seq[Input], runConfig: RunConfig): JSRun = { + runConfig.logger.debug("Using input file: " + (input.mkString(","))) NodeJSEnv.internalStart(logger, config, env)(NodeJSEnv.write(input), runConfig) } @@ -290,7 +291,10 @@ object NodeJSEnv { import scala.concurrent.ExecutionContext.Implicits.global private val isClosed = AtomicBoolean(false) - override def future: Future[Unit] = cancellable.map(_ => ()) + override def future: Future[Unit] = cancellable.map { results => + logger.debug(s"Finished with results: ${results}") + () + } override def close(): Unit = { // Make sure we only destroy the process once, the test adapter can call this several times! if (!isClosed.getAndSet(true)) {