Scala DOM Test Utils
"com.raquo" %%% "domtestutils" % "0.13.0" // Scala.js 1.3.1+ only
The types of DOM tags, attributes, properties and styles are provided by Scala DOM Types, but you don't need to be using that library in your application code, Scala DOM TestUtils can test any DOM node no matter how it was created.
You can use Scala DOM Test Utils either directly to make assertions, or you if you're writing a DOM construction / manipulation library, to power its own test utils package.
// Create a JS DOM node that you want to test (example shows optional Scala DOM Builder syntax) val jsDomNode: org.scalajs.dom.Node = div( rel := "yolo" span("Hello, "), p("bizzare ", a(href := "http://y2017.com", "2017"), span(" world")), hr ).ref // Mount the DOM node for testing mount(jsDomNode, "optional clue to show on failure") // Assert that the mounted node matches the provided description (this test will pass given the input above) expectNode( div.of( rel is "yolo", // Ensure that rel attribute is "yolo". Note: assertions for properties and styles work similarly span.of("Hello, "), // Ensure the this element contains just one text node: "Hello, " p.of( "bizzare ", a.of( href is "http://y2017.com", title.isEmpty, // Ensure that title attribute is not set "2017" ), span.of(" world") ), hr // Just check existence of element and tag name. Equivalent to `hr like ()` ) )
The above example defines
See more usage examples in Laminar tests
Canonical usage is to
mount one DOM node / tree (e.g. the output of your component) and then test it using the
Alternative is to call
expectNode(actualNode, expectedNode), for example if you only want to test a subtree of what you mounted.
If the mechanics of
MountOps do not work for you, you can bypass
MountOps altogether and just call
ExpectedNode.checkNode(actualNode) directly to get a list of errors.
With ScalaTest: Your test suite should extend the
MountSpec[Any] trait. Use
expectNode methods in your test code. You can call
unmount and then
mount again within one test if you want to test multiple unrelated nodes (e.g. different variations in a loop).
AsyncMountSpec provides similar functionality for async tests.
Without ScalaTest: Write a tiny adapter like
MountSpec for your test framework, which would:
doFailimplementations specific to your test framework
resetDOMin the beginning of each test, and
clearDOMat the end of each test.
Pull requests for such adapters for popular test frameworks are welcome.
To power your library's test utils: If you are building or using a DOM construction / manipulation library like e.g. React, you might want to override the
unmount methods to give your library the chance to do proper setup and cleanup. Instead of calling super methods for these, you can make use of
mountedElementClue the same way they are used in the default implementations in
If all this is more hassle than it's worth for your use case, just forgo
MountOps and drop down to calling
ExpectedNode.checkNode(actualNode) to get a list of errors, and build your own test util around it.
- Docs: Add examples without Scala DOM Builder, in this library's own test suite
- Docs: Explain in more detail how to make assertions
- Docs: Explain the basics of Scala DOM Types node / attr / etc. types
- Docs: Explain how to create your own custom rules
- Docs: Document available assertions
- Feature: Add
maybeMoreChildrento allow shallow / focused matching
My Related Projects
- Scala DOM Types – Type definitions that we use for all the HTML tags, attributes, properties, and styles
- Laminar – Reactive UI library based on Scala DOM Types
- Scala DOM Builder – Low-level library for building and manipulating DOM trees
Nikita Gazarov – @raquo
License – MIT