Skip to content

Commit

Permalink
bump react to 18.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
rpiaggio committed Jan 29, 2024
1 parent 48ed253 commit dc8a164
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 189 deletions.
171 changes: 84 additions & 87 deletions doc/TESTING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
Testing
=======
# Testing

This file describes testing functionality provided by React.JS and scalajs-react.
<br>It is plenty for simple and small unit tests.
Expand All @@ -10,6 +9,7 @@ For larger and/or complicated tests, **it is highly recommended to use
for how to write tests for real-world scalajs-react applications.

#### Contents

- [Setup](#setup)
- [`ReactTestUtils`](#reacttestutils)
- [`Simulate` and `Simulation`](#simulate-and-simulation)
Expand All @@ -18,69 +18,70 @@ for how to write tests for real-world scalajs-react applications.
- [`Test Scripts`](#test-scripts)
- [Fatal React warnings](#fatal-react-warnings)

Setup
=====
# Setup

1. Install PhantomJS.

2. Add the following to SBT:

```scala
// scalajs-react test module
libraryDependencies += "com.github.japgolly.scalajs-react" %%% "test" % "2.1.1" % Test

// React JS itself.
// NOTE: Requires react-with-addons.js instead of just react.js
jsDependencies +=
```scala
// scalajs-react test module
libraryDependencies += "com.github.japgolly.scalajs-react" %%% "test" % "2.1.1" % Test

"org.webjars.npm" % "react-dom" % "18.1.0" % Test
/ "umd/react-dom-test-utils.development.js"
minified "umd/react-dom-test-utils.production.min.js"
dependsOn "umd/react-dom.development.js"
commonJSName "ReactTestUtils"
```
// React JS itself.
// NOTE: Requires react-with-addons.js instead of just react.js
jsDependencies +=

"org.webjars.npm" % "react-dom" % "18.2.0" % Test
/ "umd/react-dom-test-utils.development.js"
minified "umd/react-dom-test-utils.production.min.js"
dependsOn "umd/react-dom.development.js"
commonJSName "ReactTestUtils"
```

`ReactTestUtils`
================
# `ReactTestUtils`

The main bucket of testing utilities lies in `japgolly.scalajs.react.test.ReactTestUtils`.

Half of the methods delegate to React.JS's [React.addons.TestUtils](https://facebook.github.io/react/docs/test-utils.html)
(for which there is a raw facade in `japgolly.scalajs.react.test.raw.ReactAddonsTestUtils` if you're interested).

The other half are new functions added specifically in scalajs-react.
* Rendering into DOM with auto-removal
* `withRendered[M, A](u: Unmounted[M], intoBody: Boolean)(f: M => A): A`
* `withRenderedIntoDocument[M, A](u: Unmounted[M])(f: M => A): A`
* `withRenderedIntoBody[M, A](u: Unmounted[M])(f: M => A): A`
* `withNewBodyElement[A](use: Element => A): A`
* `newBodyElement(): Element`
* `removeNewBodyElement(e: Element): Unit`
* `renderIntoBody[M, A](u: Unmounted[M]): M`
* Asynchronously rendering into DOM with auto-removal
* `withRenderedAsync[M, A](u: Unmounted[M], intoBody: Boolean)(f: M => Future[A]): Future[A]`
* `withRenderedIntoDocumentAsync[M, A](u: Unmounted[M])(f: M => Future[A]): Future[A]`
* `withRenderedIntoBodyAsync[M, A](u: Unmounted[M])(f: M => Future[A]): Future[A]`
* `withNewBodyElementAsync[A](use: Element => Future[A]): Future[A]`
* Mounted props modification
* `replaceProps(component, mounted)(newProps: P): mounted'`
* `modifyProps(component, mounted)(f: P => P): mounted'`
* Other
* `removeReactInternals(html: String): String` - Removes internal annotations from HTML that React inserts.

- Rendering into DOM with auto-removal
- `withRendered[M, A](u: Unmounted[M], intoBody: Boolean)(f: M => A): A`
- `withRenderedIntoDocument[M, A](u: Unmounted[M])(f: M => A): A`
- `withRenderedIntoBody[M, A](u: Unmounted[M])(f: M => A): A`
- `withNewBodyElement[A](use: Element => A): A`
- `newBodyElement(): Element`
- `removeNewBodyElement(e: Element): Unit`
- `renderIntoBody[M, A](u: Unmounted[M]): M`
- Asynchronously rendering into DOM with auto-removal
- `withRenderedAsync[M, A](u: Unmounted[M], intoBody: Boolean)(f: M => Future[A]): Future[A]`
- `withRenderedIntoDocumentAsync[M, A](u: Unmounted[M])(f: M => Future[A]): Future[A]`
- `withRenderedIntoBodyAsync[M, A](u: Unmounted[M])(f: M => Future[A]): Future[A]`
- `withNewBodyElementAsync[A](use: Element => Future[A]): Future[A]`
- Mounted props modification
- `replaceProps(component, mounted)(newProps: P): mounted'`
- `modifyProps(component, mounted)(f: P => P): mounted'`
- Other
- `removeReactInternals(html: String): String` - Removes internal annotations from HTML that React inserts.

There's only one magic implicit method this time around:
Mounted components get `.outerHtmlScrubbed()` which is shorthand for
`ReactTestUtils.removeReactInternals(m.getDOMNode.outerHTML)`.

`Simulate` and `Simulation`
===========================
# `Simulate` and `Simulation`

To make event simulation easier, certain event types have dedicated, strongly-typed case classes to wrap event data. For example, JS like

```js
// JavaScript
ReactAddons.TestUtils.Simulate.change(t, {target: {value: "Hi"}})
ReactAddons.TestUtils.Simulate.change(t, { target: { value: "Hi" } });
```

becomes

```scala
// Scala
Simulate.change(t, SimEvent.Change(value = "Hi"))
Expand All @@ -94,6 +95,7 @@ If you'd like more composability and/or purity there's also `Simulation` which
represents action (without a target). It does nothing until `.run` is called and a target is provided.

Example:

```scala
val a = Simulation.focus
val b = Simulation.change(SimEvent.Change(value = "hi"))
Expand All @@ -110,14 +112,13 @@ val s = Simulation.focusChangeBlur("hi")
s run component
```


Testing props changes
=====================
# Testing props changes

When you want to simulate a parent component re-rendering a child component with different props,
you can test the child directly using `ReactTestUtils.{modify,replace}Props`.

Example of code to test:

```scala
class CP {
var prev = "none"
Expand All @@ -131,6 +132,7 @@ val CP = ScalaComponent.builder[String]("asd")
```

Example test case:

```scala
ReactTestUtils.withRenderedIntoDocument(CP("start")) { m =>
assert(m.outerHtmlScrubbed(), "<div>none → start</div>")
Expand All @@ -143,16 +145,15 @@ ReactTestUtils.withRenderedIntoDocument(CP("start")) { m =>
}
```


`ReactTestVar`
==============
# `ReactTestVar`

A `ReactTestVar[A]` is a wrapper around a `var a: A` that:
* can produce a `StateSnapshot[A]` with or without `Reusability`
* can produce a `StateAccess[A]`
* retains history when modified
* can perform arbitrary actions when modified
* can be reset

- can produce a `StateSnapshot[A]` with or without `Reusability`
- can produce a `StateAccess[A]`
- retains history when modified
- can perform arbitrary actions when modified
- can be reset

It's useful for testing components that accept `StateSnapshot[A]`/`StateAccess[A]` instances
in their props.
Expand Down Expand Up @@ -207,62 +208,58 @@ ReactTestUtils.withRenderedIntoDocument(component(testVar.stateAccess)) { m =>
}
```


Test Scripts
============
# Test Scripts

It's possible to write test scripts like

1. *click this*
2. *verify that*
3. *press the Back button*
4. *type name*
5. *press Enter*
1. _click this_
2. _verify that_
3. _press the Back button_
4. _type name_
5. _press Enter_

In case you missed the notice at the top of the file, that functionality is provided in a sister library called
[Scala Test-State](https://github.com/japgolly/test-state).

See [this example](https://github.com/japgolly/test-state/tree/master/example-react)
for how to write tests for real-world scalajs-react applications.


Fatal React warnings
====================
# Fatal React warnings

The easiest way to make `ReactTestUtils` to turn React warnings into runtime exceptions,
is via a [config option](./CONFIG.md#testwarningsreact).

Alternatively, you can do any of the following...

* Wrapping a test
- Wrapping a test

```scala
import japgolly.scalajs.react.test.ReactTestUtilsConfig
ReactTestUtilsConfig.AroundReact.fatalReactWarnings {
// test code here
}
```
```scala
import japgolly.scalajs.react.test.ReactTestUtilsConfig
ReactTestUtilsConfig.AroundReact.fatalReactWarnings {
// test code here
}
```

* Installing for all `ReactTestUtils` usage
- Installing for all `ReactTestUtils` usage

```scala
import japgolly.scalajs.react.test.ReactTestUtilsConfig
ReactTestUtilsConfig.aroundReact.set(
ReactTestUtilsConfig.AroundReact.fatalReactWarnings)
```
```scala
import japgolly.scalajs.react.test.ReactTestUtilsConfig
ReactTestUtilsConfig.aroundReact.set(
ReactTestUtilsConfig.AroundReact.fatalReactWarnings)
```

* Installing outside of test code
- Installing outside of test code

```scala
import japgolly.scalajs.react.util.ConsoleHijack
ConsoleHijack.fatalReactWarnings.install()
```
```scala
import japgolly.scalajs.react.util.ConsoleHijack
ConsoleHijack.fatalReactWarnings.install()
```

* Wrapping non-test code
- Wrapping non-test code

```scala
import japgolly.scalajs.react.util.ConsoleHijack
ConsoleHijack.fatalReactWarnings {
// code here
}
```
```scala
import japgolly.scalajs.react.util.ConsoleHijack
ConsoleHijack.fatalReactWarnings {
// code here
}
```
Loading

0 comments on commit dc8a164

Please sign in to comment.