Testing Typescript Projects
This page will discuss common topics around working with test suites using the Mill build tool
Defining Unit Test Suites
package build
import mill._, javascriptlib._
object bar extends TypeScriptModule {
object test extends TypeScriptTests with TestModule.Jest
}
object baz extends TypeScriptModule {
object test extends TypeScriptTests with TestModule.Vitest
}
object foo extends TypeScriptModule {
object test extends TypeScriptTests with TestModule.Mocha
}
object qux extends TypeScriptModule {
object test extends TypeScriptTests with TestModule.Jasmine
}
This build defines 4 modules bar, baz, foo & qux with test suites configured to use Jest, Vitest, Mocha & Jasmine respectively.
Mill will auto-magically generate test configurations for each respective test suite.
Custom test configurations can be used by simply including a matching test suite config file in your project root,
same directory as your build.mill
file.
You can view the generated config file by looking in the compile
destination for your modules test.
For example, the module bar
will have its jest.config.ts
file live in out/bar/test/compile.dest/
.
It is important to note, that for most use cases you will never need to define a custom test configurtion file.
For custom configurations:
Jest suite expects a jest.config.ts
file.
Jasmine suite expects a jasmine.json
file.
Mocha suite expects a test-runner.js
file.
Vitest suite expects a vitest.config.ts
file.
> mill foo.test
...
...4 passing...
...
> mill bar.test
...Calculator
...
Test Suites:...1 passed, 1 total...
Tests:...4 passed, 4 total...
...
> mill baz.test
.../calculator.test.ts...
...Test Files 1 passed...
...Tests 4 passed...
...
> mill qux.test
...
4 specs, 0 failures
Test Dependencies
package build
import mill._, javascriptlib._
object bar extends TypeScriptModule {
def npmDeps = Seq("immutable@4.3.7")
object test extends TypeScriptTests with TestModule.Jest
}
object foo extends TypeScriptModule {
def moduleDeps = Seq(bar)
object test extends TypeScriptTests with TestModule.Jest
}
Documentation for mill.example.javascriptlib
In this example, foo
depend on bar
, but we also make
foo.test
depend on bar.test
.
That lets foo.test
make use of the default function exported from
bar/test/utils/bar.tests.utils.ts
, allowing us to re-use this
test helper throughout multiple modules' test suites.
> mill foo.test
PASS .../foo.test.ts
...
Test Suites:...1 passed, 1 total...
Tests:...3 passed, 3 total...
...
> mill bar.test
PASS .../bar.test.ts
...
Test Suites:...1 passed, 1 total...
Tests:...1 passed, 1 total...
...
Integration Suite with Cypress
package build
import mill._, javascriptlib._
object client extends ReactScriptsModule
object server extends TypeScriptModule {
def npmDeps =
Seq("@types/cors@^2.8.17", "@types/express@^5.0.0", "cors@^2.8.5", "express@^4.21.1")
/** Bundle client as resource */
def resources = Task {
os.copy(client.bundle().path, Task.dest / "build")
super.resources() ++ Seq(PathRef(Task.dest))
}
override def forkEnv = super.forkEnv() + ("PORT" -> "4000")
object test extends TypeScriptTests with TestModule.Cypress {
def service = server
def port = "4000"
}
}
Documentation for mill.example.javascriptlib
In this example we demonstrate integration testing using cypress
mill server.test
will start the service on the speicifed port, run tests with configurations defined in cypress.config.ts
and kill the service once completed
> mill server.test
...
...Server listening on port 4000
... app.cy.ts...
... All specs passed!...
...
Integration Suite with PlayWright
package build
import mill._, javascriptlib._
object client extends ReactScriptsModule
object server extends TypeScriptModule {
def npmDeps =
Seq("@types/cors@^2.8.17", "@types/express@^5.0.0", "cors@^2.8.5", "express@^4.21.1")
/** Bundle client as resource */
def resources = Task {
os.copy(client.bundle().path, Task.dest / "build")
super.resources() ++ Seq(PathRef(Task.dest))
}
def forkEnv = super.forkEnv() + ("PORT" -> "3000")
object test extends TypeScriptTests with TestModule.PlayWright {
def service = server
def port = "6000"
}
}
Documentation for mill.example.javascriptlib
In this example we demonstrate integration testing using playwright
mill server.test
will start the service on the speicifed port, run tests with configurations defined in playwright.config.ts
and kill the service once completed
> mill server.test
...
...Server listening on port 6000
...
...1 passed...
...