Serving the app
E2E needs a URL. Chekhov owns scoped serve so the server or process dies with the test Scope
(success, failure, or interrupt). Process logs land under artifactsDir/serve.
Static files
For a directory of HTML/JS with no bundler, StaticFileServer is the default recipe. It binds an
ephemeral port on 127.0.0.1, serves the directory (index.html at /), and yields an
AppServer whose baseUrl you point ChekhovConfig.baseUrl at:
import chekhov.*
import zio.*
import java.nio.file.Path
val server = StaticFileServer.layer(Path.of("path/to/static"))
Same Scope story as any other layer: the server stops when the test scope closes.
object StaticSpec extends ChekhovSuite:
override def chekhovConfig =
ChekhovConfig(baseUrl = Some("http://127.0.0.1:8080"))
override def chekhovLayerFor(cfg: ChekhovConfig) =
ZLayer.succeed(cfg) >>>
(StaticFileServer.layer(Path.of("examples/static-fixture")) ++ ChekhovSuite.processStack)
Scala.js / ascent (sbt-splice)
For a Scala.js or ascent fixture there is no dev server to run. sbt-splice links one
self-contained fast.js; stage it next to an index.html, then serve that directory with
StaticFileServer:
// build.sbt: spliceFastOutput := baseDirectory.value / "target" / "serve" / "fast.js"
// a staging task writes target/serve/index.html that loads ./fast.js, then:
StaticFileServer.layer(Path.of("examples/ascent-fixture/target/serve"))
This repo's ascent-fixture does exactly this: stageAscentFixture stages index.html plus the
spliceFast output under target/serve. Chekhov only serves the directory and drives the browser
once baseUrl is up; the link and stage wiring live in the consuming build.
Your own process
If you already run a dev server (any bundler, any stack), point AppServer.serve at it with a
ServeConfig. Chekhov starts the process, waits until readyUrl responds, and kills it on Scope
exit:
import chekhov.*
import java.nio.file.Path
val cfg = ServeConfig(
command = List("npm", "run", "dev"),
cwd = Path.of("my-app"),
readyUrl = "http://127.0.0.1:5173",
)
AppServer.serve(cfg) // ZIO[Scope & ChekhovConfig, ChekhovError, AppServer]
AppServer.layer(cfg) // ZLayer[ChekhovConfig, ChekhovError, AppServer]
readyTimeout (default 45s) bounds the readiness wait; env passes extra process env.
ServeConfig(
command = List("npm", "run", "dev"),
cwd = Path.of("examples/static-fixture"),
readyUrl = "http://127.0.0.1:5173"http://127.0.0.1:5173