Skip to content

Commit e399620

Browse files
authored
Merge pull request #1133 from japgolly/test_utils_deprecation
Deprecate `ReactTestUtils`
2 parents 12a07b5 + c89c798 commit e399620

File tree

29 files changed

+1047
-210
lines changed

29 files changed

+1047
-210
lines changed

doc/TESTING.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ Read through the following for how to test with `ReactTestUtils`.
4949

5050
```scala
5151
import japgolly.scalajs.react._
52-
import japgolly.scalajs.react.test._
52+
import japgolly.scalajs.react.test.ReactTestUtils
53+
import japgolly.scalajs.react.testing_library.dom.Simulate
5354
import japgolly.scalajs.react.vdom.html_<^._
5455
import utest._
5556

doc/changelog/3.0.0.md

Lines changed: 76 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 3.0.0
22

3-
### New
3+
## New
44

55
- React 18 support
66
- List of implemented features is here: https://github.com/japgolly/scalajs-react/issues/1057
@@ -27,7 +27,7 @@
2727

2828
- `Renderable` typeclass for anything that React can render
2929

30-
### Other Changes
30+
## Other Changes
3131

3232
- Allow calling `useCallback*` with sync functions that return a value.
3333

@@ -41,7 +41,7 @@
4141
- `TriStateCheckbox` no longer uses `Reusability.shouldComponentUpdate`, therefore
4242
the fourth argument to its props is no longer wrapped in `Reusable`.
4343

44-
### Deprecated
44+
## Deprecated
4545

4646
- Anything deprecated by React 18 is now deprecated in Scala
4747

@@ -51,7 +51,7 @@
5151

5252
- `ReactTestUtils` is now `LegacyReactTestUtils` and deprecated
5353

54-
### Upgrades
54+
## Upgrades
5555

5656
- Cats 2.13.0
5757
- CatsEffect 3.6.3
@@ -62,44 +62,79 @@
6262
- ScalaJsDom 2.8.1
6363
- Sourcecode 0.4.4
6464

65-
### Migration
65+
## Migration
6666

67-
- Run this to switch from `{ => Legacy}ReactTestUtils`, and if you were on the betas `ReactTestUtils{2 => }`:
67+
### `jsDependencies`
6868

69-
```sh
70-
find . -type f -name '*.scala' -exec perl -pi -e '
71-
s/\bReactTestUtils\b/LegacyReactTestUtils/g;
72-
s/\bReactTestUtils2\b/ReactTestUtils/g;
73-
' {} +
74-
```
69+
To upgrade when using `jsDependencies`, make your sbt config look like this (comments for clarity)
7570

76-
- To upgrade when using `jsDependencies`, make your sbt config look like this (comments for clarity)
71+
```scala
72+
// Required for React 18.3.1
73+
dependencyOverrides += "org.webjars.npm" % "scheduler" % "0.22.0",
7774

78-
```scala
79-
// Required for React 18.0.0
80-
dependencyOverrides += "org.webjars.npm" % "scheduler" % "0.22.0",
81-
82-
jsDependencies ++= Seq(
83-
84-
// Polyfill required for React 18.0.0
85-
"org.webjars.npm" % "fast-text-encoding" % "1.0.3" / "text.js" minified "text.min.js"
86-
87-
"org.webjars.npm" % "react" % "18.0.0"
88-
/ "umd/react.development.js"
89-
minified "umd/react.production.min.js"
90-
dependsOn "text.js" // <-- Load the fast-text-encoding polyfill before loading React itself
91-
commonJSName "React",
92-
93-
"org.webjars.npm" % "react-dom" % "18.0.0"
94-
/ "umd/react-dom.development.js"
95-
minified "umd/react-dom.production.min.js"
96-
dependsOn "umd/react.development.js"
97-
commonJSName "ReactDOM",
98-
99-
"org.webjars.npm" % "react-dom" % "18.0.0"
100-
/ "umd/react-dom-server.browser.development.js"
101-
minified "umd/react-dom-server.browser.production.min.js"
102-
dependsOn "umd/react-dom.development.js"
103-
commonJSName "ReactDOMServer",
104-
),
105-
```
75+
jsDependencies ++= Seq(
76+
77+
// Polyfill required for React 18.3.1
78+
"org.webjars.npm" % "fast-text-encoding" % "1.0.6" / "1.0.6/text.min.js" minified "text.min.js"
79+
80+
"org.webjars.npm" % "react" % "18.3.1"
81+
/ "umd/react.development.js"
82+
minified "umd/react.production.min.js"
83+
dependsOn "text.js" // <-- Load the fast-text-encoding polyfill before loading React itself
84+
commonJSName "React",
85+
86+
"org.webjars.npm" % "react-dom" % "18.3.1"
87+
/ "umd/react-dom.development.js"
88+
minified "umd/react-dom.production.min.js"
89+
dependsOn "umd/react.development.js"
90+
commonJSName "ReactDOM",
91+
92+
"org.webjars.npm" % "react-dom" % "18.3.1"
93+
/ "umd/react-dom-server.browser.development.js"
94+
minified "umd/react-dom-server.browser.production.min.js"
95+
dependsOn "umd/react-dom.development.js"
96+
commonJSName "ReactDOMServer",
97+
),
98+
```
99+
100+
### `ReactTestUtils`
101+
102+
Run this to switch from `{ => Legacy}ReactTestUtils`, and if you were on the betas `ReactTestUtils{2 => }`:
103+
104+
```sh
105+
find . -type f -name '*.scala' -exec perl -pi -e '
106+
s/\bReactTestUtils\b/LegacyReactTestUtils/g;
107+
s/\bReactTestUtils2\b/ReactTestUtils/g;
108+
' {} +
109+
```
110+
111+
### `Simulate`, `SimEvent`, `Simulation`
112+
113+
React has removed `Simulate` as of React v19. It is deprecated in React v18.
114+
115+
React now recommends using [React Testing Library](https://testing-library.com/react) instead.
116+
There is no Scala.js facade for it, and even if there was it wouldn't be a drop-in replacement.
117+
118+
As a band-aid solution, there is now a new scalajs-react module called `testing_library-dom`
119+
that builds on `@testing-library/dom` and
120+
provides a subset of `Simulate`, `SimEvent`, `Simulation` under the
121+
`japgolly.scalajs.react.testing_library.dom` package.
122+
123+
Unfortunately some types of events like `Simulate.change` do not fire and thus have been removed from the API.
124+
125+
Add this to your sbt:
126+
127+
```scala
128+
libraryDependencies += "com.github.japgolly.scalajs-react" %%% "testing_library-dom" % "3.0.0" % Test
129+
130+
jsDependencies += "org.webjars.npm" % "testing-library__dom" % "10.4.1" /
131+
"dom.umd.js" commonJSName "TestingLibraryDom" % Test
132+
```
133+
134+
and to use it:
135+
136+
```scala
137+
import japgolly.scalajs.react.testing_library.dom.Simulate
138+
139+
// Simulate.click(domNode)
140+
```

library/build.sbt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ val ghpages = ScalaJsReact.ghpages
2222
val ghpagesMacros = ScalaJsReact.ghpagesMacros
2323
val root = ScalaJsReact.root
2424
val scalafixRules = ScalaJsReact.scalafixRules
25+
val testingLibraryDom = ScalaJsReact.testingLibraryDom
2526
val tests = ScalaJsReact.tests
2627
val testsDep = ScalaJsReact.testsDep
2728
val testUtilMacros = ScalaJsReact.testUtilMacros

library/facadeTest/src/main/scala/japgolly/scalajs/react/test/facade/ReactTestUtils.scala

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ trait ReactTestUtils extends js.Object {
2828
*
2929
* This helps make your tests run closer to what real users would experience when using your application.
3030
*/
31-
@deprecated("Use React.act", "3.0.0")
31+
@deprecated("Use React.act", "3.0.0 / React v18")
3232
final def act(body: js.Function0[Any]): js.Thenable[Unit] = js.native
3333

3434
/** When writing UI tests, tasks like rendering, user events, or data fetching can be considered as "units" of
@@ -45,69 +45,83 @@ trait ReactTestUtils extends js.Object {
4545
* This helps make your tests run closer to what real users would experience when using your application.
4646
*/
4747
@JSName("act")
48-
@deprecated("Use React.actAsync", "3.0.0")
48+
@deprecated("Use React.actAsync", "3.0.0 / React v18")
4949
final def actAsync(body: js.Function0[js.Thenable[Any]]): js.Thenable[Unit] = js.native
5050

5151
/** Render a component into a detached DOM node in the document. This function requires a DOM. */
52+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
5253
final def renderIntoDocument(element: React.Element): React.ComponentUntyped | Null = js.native
5354

5455
/**
5556
* Pass a mocked component module to this method to augment it with useful methods that allow it to be used as a dummy
5657
* React component. Instead of rendering as usual, the component will become a simple &lt;div&gt; (or other tag if
5758
* mockTagName is provided) containing any provided children.
5859
*/
60+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
5961
final def mockComponent[P <: js.Object, S <: js.Object](c: React.ComponentClass[P, S], mockTagName: String = js.native): React.ComponentClass[P, S] = js.native
6062

63+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
6164
final type Mounted = React.ComponentUntyped
6265

6366
/** Returns true if instance is an instance of a React componentClass. */
67+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
6468
final def isComponentOfType(instance: React.Element, c: React.ComponentClassUntyped): Boolean = js.native
6569

6670
/** Returns true if instance is a DOM component (such as a &lt;div&gt; or &lt;span&gt;). */
71+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
6772
final def isDOMComponent(instance: React.Element): Boolean = js.native
6873

6974
/** Returns true if instance is a composite component (created with React.createClass()) */
75+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
7076
final def isCompositeComponent(instance: React.Element): Boolean = js.native
7177

7278
/** The combination of [[isComponentOfType()]] and [[isCompositeComponent()]]. */
79+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
7380
final def isCompositeComponentWithType(instance: React.Element, c: React.ComponentClassUntyped): Boolean = js.native
7481

7582
/**
7683
* Traverse all components in tree and accumulate all components where test(component) is true.
7784
* This is not that useful on its own, but it's used as a primitive for other test utils.
7885
*/
86+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
7987
final def findAllInRenderedTree(tree: Mounted, test: js.Function1[Mounted, Boolean]): js.Array[Mounted] = js.native
8088

8189
/**
8290
* Finds all instance of components in the rendered tree that are DOM components with the class name
8391
* matching className.
8492
*/
93+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
8594
final def scryRenderedDOMComponentsWithClass(tree: Mounted, className: String): js.Array[Mounted] = js.native
8695

8796
/**
8897
* Like [[scryRenderedDOMComponentsWithClass()]] but expects there to be one result, and returns that one result, or
8998
* throws exception if there is any other number of matches besides one.
9099
*/
100+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
91101
final def findRenderedDOMComponentWithClass(tree: Mounted, className: String): Mounted = js.native
92102

93103
/**
94104
* Finds all instance of components in the rendered tree that are DOM components with the tag name
95105
* matching tagName.
96106
*/
107+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
97108
final def scryRenderedDOMComponentsWithTag(tree: Mounted, tagName: String): js.Array[Mounted] = js.native
98109

99110
/**
100111
* Like [[scryRenderedDOMComponentsWithTag()]] but expects there to be one result, and returns that one result, or
101112
* throws exception if there is any other number of matches besides one.
102113
*/
114+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
103115
final def findRenderedDOMComponentWithTag(tree: Mounted, tagName: String): Mounted = js.native
104116

105117
/** Finds all instances of components with type equal to componentClass. */
118+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
106119
final def scryRenderedComponentsWithType(tree: Mounted, c: React.ComponentClassUntyped): js.Array[Mounted] = js.native
107120

108121
/**
109122
* Same as [[scryRenderedComponentsWithType()]] but expects there to be one result and returns that one result, or throws
110123
* exception if there is any other number of matches besides one.
111124
*/
125+
@deprecated("Deprecated in favour of https://testing-library.com/react", "3.0.0 / React v18")
112126
final def findRenderedComponentWithType(tree: Mounted, c: React.ComponentClassUntyped): Mounted = js.native
113127
}

library/project/Build.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ object ScalaJsReact {
3535
ghpages,
3636
ghpagesMacros,
3737
scalafixRules,
38+
testingLibraryDom,
3839
testsDep,
3940
tests,
4041
testUtilMacros,
@@ -210,9 +211,18 @@ object ScalaJsReact {
210211
)
211212
.configure(conditionallyDisable) // keep this last
212213

214+
lazy val testingLibraryDom = project
215+
.dependsOn(testUtil)
216+
.configure(commonSettings, publicationSettings, hasNoTests)
217+
.settings(
218+
moduleName := "testing_library-dom",
219+
libraryDependencies += Dep.scalaJsDom.value,
220+
)
221+
213222
lazy val tests = project
214223
.dependsOn(testUtil, coreExtCatsEffect, extraExtMonocle3)
215224
.dependsOn(coreBundleCallback) // Low priority
225+
.dependsOn(testingLibraryDom % Test)
216226
.configure(commonSettings, preventPublication, utestSettings, addReactJsDependencies(Test))
217227
.settings(
218228
Test / scalacOptions -= "-Xlint:adapted-args",
@@ -230,6 +240,7 @@ object ScalaJsReact {
230240
(ProvidedJS / "component-es6.js" dependsOn Dep.reactDom.dev) % Test,
231241
(ProvidedJS / "component-fn.js" dependsOn Dep.reactDom.dev) % Test,
232242
(ProvidedJS / "forward-ref.js" dependsOn Dep.reactDom.dev) % Test,
243+
Dep.testingLibraryDomJs.value % Test,
233244
),
234245
)
235246

library/project/Dependencies.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ object Dependencies {
1818
val scala3 = "3.3.0"
1919
val scalaJsDom = "2.8.1"
2020
val sourcecode = "0.4.4"
21+
val testingLibraryDomJs = "10.4.1"
2122

2223
// Internal
2324
val betterMonadicFor = "0.3.1"
@@ -75,9 +76,12 @@ object Dependencies {
7576
val reactDom = ReactArtifact("react-dom")
7677
val reactDomServer = ReactArtifact("react-dom-server.browser")
7778
val reactDoutestUtils = ReactArtifact("react-dom-test-utils")
79+
80+
val testingLibraryDomJs = Def.setting("org.webjars.npm" % "testing-library__dom" % Ver.testingLibraryDomJs /
81+
"dom.umd.js" commonJSName "TestingLibraryDom")
7882
}
7983

80-
def fastTextEncodingJs = "text.min.js" // 1.0.6 webjar only contains minified version
84+
def fastTextEncodingJs = s"${Ver.fastTextEncoding}/text.min.js" // 1.0.6 webjar only contains minified version
8185

8286
def globalDependencyOverrides = Def.setting(Seq(
8387
Dep.scalaJsDom.value,

library/testUtil/src/main/scala/japgolly/scalajs/react/test/ReactEventType.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ object ReactEventType {
2828
// val target : DOMEventTarget = js.native
2929
// val `type` : String = js.native
3030
js.Dynamic.literal(
31-
bubbles = false,
32-
cancelable = false,
31+
bubbles = true,
32+
cancelable = true,
3333
defaultPrevented = false,
3434
isTrusted = false,
3535
timeStamp = System.currentTimeMillis().toDouble,
@@ -172,4 +172,4 @@ object ReactEventType {
172172
deltaMode = 0, // The delta values are specified in pixels
173173
))
174174
}
175-
}
175+
}

library/testUtil/src/main/scala/japgolly/scalajs/react/test/ReactTestUtils.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ trait ReactTestUtils extends japgolly.scalajs.react.test.internal.ReactTestUtilE
3434
private val reactRaw = japgolly.scalajs.react.facade.React
3535

3636
type Unmounted = GenericComponent.Unmounted[_, Unit]
37-
3837
type CompType = GenericComponent.ComponentRaw {type Raw <: japgolly.scalajs.react.facade.React.ComponentClassUntyped }
3938

4039
// ===================================================================================================================

library/testUtil/src/main/scala/japgolly/scalajs/react/test/SimEvent.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import scala.scalajs.js.Dynamic
77
// NOTE: Do not use UndefOr for arguments below; undefined causes Phantom-bloody-JS to crash.
88
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99

10+
@deprecated("See the 3.0.0 changelog for migration details", "3.0.0 / React v18")
1011
object SimEvent {
1112

1213
case class Change(value : String = "",

library/testUtil/src/main/scala/japgolly/scalajs/react/test/Simulate.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import japgolly.scalajs.react.test.facade
55
import scala.scalajs.js
66

77
/** https://reactjs.org/docs/test-utils.html#simulate */
8+
@deprecated("See the 3.0.0 changelog for migration details", "3.0.0 / React v18")
89
object Simulate {
910
import ReactEventType._
1011

0 commit comments

Comments
 (0)