Skip to content

Commit 79f9eac

Browse files
authored
Merge pull request #1108 from japgolly/modernize-tests
Modernize tests
2 parents a612708 + 3bbb297 commit 79f9eac

File tree

53 files changed

+1390
-705
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1390
-705
lines changed

downstream-tests/build.sbt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Dependencies.Dep.utest
12
import java.util.Properties
23
import org.scalajs.linker.interface._
34
import Dependencies._
@@ -70,6 +71,8 @@ lazy val cleanTestAll = taskKey[Unit]("cleanTestAll")
7071

7172
val enableJSCE = System.getProperty("downstream_tests.enableJSCE") != null
7273

74+
val utestCE = Def.setting("org.typelevel" %%% "cats-effect-testing-utest" % "1.6.0" % Test)
75+
7376
lazy val root = Project("root", file("."))
7477
.configure(commonSettings)
7578
.aggregate(macros, jvm, js, jsCE, jsCBIO)
@@ -161,11 +164,14 @@ lazy val js = project
161164
Dep.scalaJsSecureRandom.value % Test,
162165
)
163166
},
167+
jsDependencies ++= Seq(
168+
(ProvidedJS / "polyfill.js") % Test
169+
),
164170
scalaJSLinkerConfig ~= { _
165171
.withSemantics(_
166172
.withRuntimeClassNameMapper(Semantics.RuntimeClassNameMapper.discardAll())
167173
)
168-
},
174+
}
169175
)
170176

171177
lazy val jsCE = project
@@ -181,12 +187,16 @@ lazy val jsCE = project
181187
"com.github.japgolly.scalajs-react" %%% "core-bundle-cats_effect" % ver,
182188
"com.github.japgolly.scalajs-react" %%% "extra" % ver,
183189
"com.github.japgolly.scalajs-react" %%% "test" % ver % Test,
190+
utestCE.value,
184191
Dep.microlibsCompileTime.value % Test,
185192
Dep.microlibsTestUtil.value % Test,
186193
Dep.scalaJsJavaTime.value % Test,
187194
Dep.scalaJsSecureRandom.value % Test,
188195
)
189196
},
197+
jsDependencies ++= Seq(
198+
(ProvidedJS / "polyfill.js") % Test
199+
),
190200
)
191201

192202
lazy val jsCBIO = project
@@ -202,13 +212,18 @@ lazy val jsCBIO = project
202212
"com.github.japgolly.scalajs-react" %%% "core-bundle-cb_io" % ver,
203213
"com.github.japgolly.scalajs-react" %%% "extra" % ver,
204214
"com.github.japgolly.scalajs-react" %%% "test" % ver % Test,
215+
utestCE.value,
205216
Dep.microlibsCompileTime.value % Test,
206217
Dep.microlibsTestUtil.value % Test,
207218
Dep.scalaJsJavaTime.value % Test,
208219
Dep.scalaJsSecureRandom.value % Test,
209220
)
210221
},
222+
jsDependencies ++= Seq(
223+
(ProvidedJS / "polyfill.js") % Test
224+
),
211225
)
226+
212227

213228
lazy val generic = project
214229
.enablePlugins(ScalaJSPlugin)

downstream-tests/flake.nix

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
inputs = {
3+
typelevel-nix.url = "github:typelevel/typelevel-nix";
4+
nixpkgs.follows = "typelevel-nix/nixpkgs";
5+
flake-utils.follows = "typelevel-nix/flake-utils";
6+
};
7+
8+
outputs = { self, nixpkgs, flake-utils, typelevel-nix }:
9+
flake-utils.lib.eachDefaultSystem (system:
10+
let
11+
pkgs-x86_64 = import nixpkgs { system = "x86_64-darwin"; };
12+
scala-cli-overlay = final: prev: { scala-cli = pkgs-x86_64.scala-cli; };
13+
pkgs = import nixpkgs {
14+
inherit system;
15+
overlays = [ typelevel-nix.overlays.default scala-cli-overlay];
16+
};
17+
in
18+
{
19+
devShell = pkgs.devshell.mkShell {
20+
imports = [ typelevel-nix.typelevelShell ];
21+
packages = [
22+
pkgs.nodePackages.typescript-language-server
23+
pkgs.nodePackages.vscode-langservers-extracted
24+
pkgs.nodePackages.prettier
25+
pkgs.nodePackages.typescript
26+
pkgs.nodePackages.graphqurl
27+
pkgs.hasura-cli
28+
];
29+
typelevelShell = {
30+
nodejs.enable = true;
31+
jdk.package = pkgs.jdk11;
32+
};
33+
env = [
34+
{
35+
name = "NODE_OPTIONS";
36+
value = "--max-old-space-size=8192";
37+
}
38+
];
39+
};
40+
}
41+
42+
);
43+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
const outerRealmFunctionConstructor = Node.constructor;
2+
window.require = new outerRealmFunctionConstructor("return require")();
3+
4+
window.MessageChannel = require('worker_threads').MessageChannel;

downstream-tests/js-cbio/src/test/scala/downstream/CBIOBundleTests.scala

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,20 @@
11
package downstream
22

3-
import concurrent.ExecutionContext.Implicits.global
43
import japgolly.microlibs.testutil.TestUtil._
54
import japgolly.scalajs.react.test.ReactTestUtils2
6-
import scala.concurrent.Future
7-
import scala.concurrent.Promise
8-
import scalajs.js
95
import utest._
6+
import cats.effect.testing.utest.EffectTestSuite
7+
import cats.effect.IO
8+
import scala.concurrent.duration._
109

11-
object CBIOBundleTests extends TestSuite {
12-
13-
private def delay(milliseconds: Int): Future[Unit] = {
14-
val p = Promise[Unit]()
15-
js.timers.setTimeout(milliseconds) {
16-
p.success(())
17-
}
18-
p.future
19-
}
10+
object CBIOBundleTests extends EffectTestSuite[IO] {
2011

2112
override def tests = Tests {
2213
Globals.clear()
2314

2415
"catnip" - {
25-
ReactTestUtils2.withRendered(Catnip.Component("omg")).future { m =>
26-
delay(500).map { _ =>
16+
ReactTestUtils2.withRendered(Catnip.Component("omg")) { m =>
17+
IO.sleep(500.millis).map { _ =>
2718
assertEq(Globals.catnipMounts, List("omg"))
2819
m.outerHTML.assert("<div>Hello(1) omg</div>")
2920
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
const outerRealmFunctionConstructor = Node.constructor;
2+
window.require = new outerRealmFunctionConstructor("return require")();
3+
4+
window.MessageChannel = require('worker_threads').MessageChannel;

downstream-tests/js-ce/src/test/scala/downstream/CatsEffectBundleTests.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,21 @@ package downstream
33
import japgolly.microlibs.testutil.TestUtil._
44
import japgolly.scalajs.react.test.ReactTestUtils2
55
import utest._
6+
import cats.effect.testing.utest.EffectTestSuite
7+
import cats.effect.IO
68

7-
object CatsEffectBundleTests extends TestSuite {
9+
object CatsEffectBundleTests extends EffectTestSuite[IO] {
810

911
override def tests = Tests {
1012
Globals.clear()
1113

1214
"catnip" - {
13-
ReactTestUtils2.withRendered(Catnip.Component("omg")) { m =>
15+
ReactTestUtils2.withRendered_(Catnip.Component("omg")) { m =>
1416
assertEq(Globals.catnipMounts, List("omg"))
1517
m.outerHTML.assert("<div>Hello omg</div>")
16-
}
17-
assertEq(Globals.catnipMounts, List("omg"))
18+
}.map(_ =>
19+
assertEq(Globals.catnipMounts, List("omg"))
20+
)
1821
}
1922

2023
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
const outerRealmFunctionConstructor = Node.constructor;
2+
window.require = new outerRealmFunctionConstructor("return require")();
3+
4+
window.MessageChannel = require('worker_threads').MessageChannel;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package japgolly.scalajs.react
2+
3+
import scala.concurrent.{ExecutionContext, Future}
4+
import scala.reflect.ClassTag
5+
import utest.TestSuite
6+
7+
abstract class AsyncTestSuite extends TestSuite {
8+
private val Tag = implicitly[ClassTag[AsyncCallback[Any]]]
9+
10+
override def utestWrap(path: Seq[String], runBody: => Future[Any])(implicit ec: ExecutionContext): Future[Any] = {
11+
runBody flatMap {
12+
case Tag(ac) => ac.unsafeToFuture()
13+
case other => super.utestWrap(path, Future.successful(other))
14+
}
15+
}
16+
}
Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
package downstream
1+
// package downstream
22

3-
import japgolly.microlibs.testutil.TestUtil._
4-
import utest._
3+
// TODO: Reimplement when we release 3.0.0
54

6-
object MimaTests extends TestSuite {
5+
// import japgolly.microlibs.testutil.TestUtil._
6+
// import utest._
77

8-
override def tests = Tests {
8+
// object MimaTests extends TestSuite {
99

10-
// "2_0_0" - {
11-
// import mima200._
10+
// override def tests = Tests {
1211

13-
// "HookUseRef" - HookUseRef.test { ref =>
14-
// val a = ref.value
15-
// val b = ref.map(_ + 1).unsafeGet()
16-
// assertEq(b, a + 1)
17-
// }
18-
// }
19-
}
20-
}
12+
// "2_0_0" - {
13+
// import mima200._
14+
15+
// "HookUseRef" - HookUseRef.test { ref =>
16+
// val a = ref.value
17+
// val b = ref.map(_ + 1).unsafeGet()
18+
// assertEq(b, a + 1)
19+
// }
20+
// }
21+
// }
22+
// }

downstream-tests/js/src/test/scala/downstream/RuntimeTests.scala

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import scala.scalajs.js
1212
import scala.scalajs.LinkingInfo.developmentMode
1313
import scala.util.Try
1414
import utest._
15+
import japgolly.scalajs.react.AsyncTestSuite
1516

16-
object RuntimeTests extends TestSuite {
17+
object RuntimeTests extends AsyncTestSuite {
1718

1819
val compNameAuto = CompileTimeInfo.sysProp("japgolly.scalajs.react.component.names.implicit")
1920
val compNameAll = CompileTimeInfo.sysProp("japgolly.scalajs.react.component.names.all")
@@ -64,45 +65,51 @@ object RuntimeTests extends TestSuite {
6465
val (promise, completePromise) = JsUtil.newPromise[Unit]()
6566
val io = IO(completePromise(Try(()))())
6667

67-
ReactTestUtils2.withRendered(Carrot.Props("1", io).render) { m =>
68-
m.root.render(Carrot.Props("1").render)
69-
m.root.render(Carrot.Props("2").render)
70-
}
71-
ReactTestUtils2.withRendered(Pumpkin.Component("1")) { m =>
72-
m.root.render(Pumpkin.Component("1"))
73-
m.root.render(Pumpkin.Component("2"))
74-
}
75-
76-
assertEq(Globals.carrotMountsA, 1)
77-
assertEq(Globals.carrotMountsB, 1)
78-
assertEq(Globals.carrotRenders, expectedCarrots)
79-
assertEq(Globals.pumpkinRenders, expectedPumpkins)
80-
81-
AsyncCallback
82-
.fromJsPromise(promise)
83-
.map(_ => s"carrots: ${Globals.carrotRenders}/3, pumpkins: ${Globals.pumpkinRenders}/3, reusabilityLog: ${Globals.reusabilityLog.length}")
84-
.timeoutMs(3000)
85-
.map(_.get)
86-
.unsafeToFuture()
68+
for {
69+
_ <- ReactTestUtils2.withRendered(Carrot.Props("1", io).render) { m =>
70+
for {
71+
_ <- m.root.render(Carrot.Props("1").render)
72+
_ <- m.root.render(Carrot.Props("2").render)
73+
} yield ()
74+
}
75+
_ <- ReactTestUtils2.withRendered(Pumpkin.Component("1")) { m =>
76+
for {
77+
_ <- m.root.render(Pumpkin.Component("1"))
78+
_ <- m.root.render(Pumpkin.Component("2"))
79+
} yield ()
80+
}
81+
_ = assertEq(Globals.carrotMountsA, 1)
82+
_ = assertEq(Globals.carrotMountsB, 1)
83+
_ = assertEq(Globals.carrotRenders, expectedCarrots)
84+
_ = assertEq(Globals.pumpkinRenders, expectedPumpkins)
85+
_ <-
86+
AsyncCallback
87+
.fromJsPromise(promise)
88+
.map(_ => s"carrots: ${Globals.carrotRenders}/3, pumpkins: ${Globals.pumpkinRenders}/3, reusabilityLog: ${Globals.reusabilityLog.length}")
89+
.timeoutMs(3000)
90+
.map(_.get)
91+
} yield ()
8792
}
8893

8994
"testWarnings" - {
9095

9196
"react" - {
9297
val c = ScalaFnComponent[Int](i => <.p(<.td(s"i = $i")))
93-
val t = Try(ReactTestUtils2.withRendered(c(123))(_ => ()))
94-
assertEq(t.isFailure, testWarningsReact.contains("react"))
98+
ReactTestUtils2.withRendered_(c(123))(_ => ()).attemptTry.map { t =>
99+
assertEq(t.isFailure, testWarningsReact.contains("react"))
100+
}
95101
}
96102

97103
"unlreated" - {
98104
val c = ScalaFnComponent[Int](i => <.p(s"i = $i"))
99-
val t = Try(ReactTestUtils2.withRendered(c(123)) { _ =>
105+
ReactTestUtils2.withRendered_(c(123)) { _ =>
100106
console.info(".")
101107
console.log(".")
102108
console.warn(".")
103109
console.error(".")
104-
})
105-
assertEq(t.isFailure, false)
110+
}.attemptTry.map { t =>
111+
assertEq(t.isFailure, false)
112+
}
106113
}
107114
}
108115
}

downstream-tests/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"dependencies": {
3+
"jsdom": "^25.0.1"
4+
}
5+
}

downstream-tests/scalafix.sbt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ ThisBuild / semanticdbEnabled := true
1212

1313
ThisBuild / semanticdbVersion := "4.12.0"
1414

15-
ThisBuild / scalafixScalaBinaryVersion := "2.13"
16-
1715
ThisBuild / scalafixDependencies += {
1816
val ver = version.value.stripSuffix("-SNAPSHOT") + "-SNAPSHOT"
1917
"com.github.japgolly.scalajs-react" %% "scalafix" % ver

library/coreGeneric/src/main/scala/japgolly/scalajs/react/CtorType.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ object CtorType {
246246
new Summoner[P, C] {
247247
override type CT[-p, +u] = T[p, u]
248248
override val summon = f
249-
override implicit val pf = p
249+
override implicit val pf: Profunctor[T] = p
250250
}
251251

252252
implicit def summonN[P <: js.Object](implicit s: Singleton[P]): Summoner.Aux[P, ChildrenArg.None, Nullary] =

library/coreGeneric/src/main/scala/japgolly/scalajs/react/SetStateFns.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ final class SetStateFn[F[_], A[_], S](underlyingFn: (Option[S], F[Unit]) => F[Un
1111
override type WithEffect [G[_]] = SetStateFn[G, A, S]
1212
override type WithAsyncEffect[G[_]] = SetStateFn[F, G, S]
1313

14-
override protected implicit def F = FF
15-
override protected implicit def A = AA
14+
override protected implicit def F: UnsafeSync[F] = FF
15+
override protected implicit def A: Async[A] = AA
1616

1717
override def withEffect[G[_]](implicit G: UnsafeSync[G]) =
1818
G.subst[F, WithEffect](this)(new SetStateFn(G.transSyncFn2C(underlyingFn)(F))(G, A))(F)
@@ -51,8 +51,8 @@ final class ModStateFn[F[_], A[_], S](underlyingFn: (S => Option[S], F[Unit]) =>
5151
override type WithEffect [G[_]] = ModStateFn[G, A, S]
5252
override type WithAsyncEffect[G[_]] = ModStateFn[F, G, S]
5353

54-
override protected implicit def F = FF
55-
override protected implicit def A = AA
54+
override protected implicit def F: UnsafeSync[F] = FF
55+
override protected implicit def A: Async[A] = AA
5656

5757
override def withEffect[G[_]](implicit G: UnsafeSync[G]) =
5858
G.subst[F, WithEffect](this)(new ModStateFn(G.transSyncFn2C(underlyingFn)(F))(G, A))(F)
@@ -94,8 +94,8 @@ final class ModStateWithPropsFn[F[_], A[_], P, S](underlyingFn: ((S, P) => Optio
9494
override type WithEffect [G[_]] = ModStateWithPropsFn[G, A, P, S]
9595
override type WithAsyncEffect[G[_]] = ModStateWithPropsFn[F, G, P, S]
9696

97-
override protected implicit def F = FF
98-
override protected implicit def A = AA
97+
override protected implicit def F: UnsafeSync[F] = FF
98+
override protected implicit def A: Async[A] = AA
9999

100100
override def withEffect[G[_]](implicit G: UnsafeSync[G]) =
101101
G.subst[F, WithEffect](this)(new ModStateWithPropsFn(G.transSyncFn2C(underlyingFn)(F))(G, A))(F)

0 commit comments

Comments
 (0)