diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70aac821..a28dc1bd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,32 +27,37 @@ jobs: name: Build and Test strategy: matrix: - os: [ubuntu-latest] - scala: [2.12.16, 3.1.3, 2.13.8] + os: [ubuntu-22.04] + scala: [2.12.18, 3.3.0, 2.13.11] java: [temurin@8, temurin@17] + project: [rootJS, rootJVM, rootNative] exclude: - - scala: 2.12.16 + - scala: 2.12.18 + java: temurin@17 + - scala: 3.3.0 + java: temurin@17 + - project: rootJS java: temurin@17 - - scala: 3.1.3 + - project: rootNative java: temurin@17 runs-on: ${{ matrix.os }} steps: - name: Checkout current branch (full) - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Download Java (temurin@8) id: download-java-temurin-8 if: matrix.java == 'temurin@8' - uses: typelevel/download-java@v1 + uses: typelevel/download-java@v2 with: distribution: temurin java-version: 8 - name: Setup Java (temurin@8) if: matrix.java == 'temurin@8' - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: jdkfile java-version: 8 @@ -61,21 +66,21 @@ jobs: - name: Download Java (temurin@17) id: download-java-temurin-17 if: matrix.java == 'temurin@17' - uses: typelevel/download-java@v1 + uses: typelevel/download-java@v2 with: distribution: temurin java-version: 17 - name: Setup Java (temurin@17) if: matrix.java == 'temurin@17' - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: jdkfile java-version: 17 jdkFile: ${{ steps.download-java-temurin-17.outputs.jdkFile }} - name: Cache sbt - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ~/.sbt @@ -87,36 +92,44 @@ jobs: key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - name: Check that workflows are up to date - run: sbt '++${{ matrix.scala }}' 'project /' githubWorkflowCheck + run: sbt githubWorkflowCheck - name: Check headers and formatting - if: matrix.java == 'temurin@8' - run: sbt '++${{ matrix.scala }}' headerCheckAll scalafmtCheckAll 'project /' scalafmtSbtCheck + if: matrix.java == 'temurin@8' && matrix.os == 'ubuntu-22.04' + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' headerCheckAll scalafmtCheckAll 'project /' scalafmtSbtCheck + + - name: scalaJSLink + if: matrix.project == 'rootJS' + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' Test/scalaJSLinkerResult + + - name: nativeLink + if: matrix.project == 'rootNative' + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' Test/nativeLink - name: Test - run: sbt '++${{ matrix.scala }}' test + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' test - name: Check binary compatibility - if: matrix.java == 'temurin@8' - run: sbt '++${{ matrix.scala }}' mimaReportBinaryIssues + if: matrix.java == 'temurin@8' && matrix.os == 'ubuntu-22.04' + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' mimaReportBinaryIssues - name: Generate API documentation - if: matrix.java == 'temurin@8' - run: sbt '++${{ matrix.scala }}' doc + if: matrix.java == 'temurin@8' && matrix.os == 'ubuntu-22.04' + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' doc - name: Make target directories if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/series/2.x') - run: mkdir -p target js/target jvm/target site/target project/target + run: mkdir -p js/target target .js/target site/target jvm/target .jvm/target .native/target native/target project/target - name: Compress target directories if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/series/2.x') - run: tar cf targets.tar target js/target jvm/target site/target project/target + run: tar cf targets.tar js/target target .js/target site/target jvm/target .jvm/target .native/target native/target project/target - name: Upload target directories if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/series/2.x') - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-${{ matrix.scala }} + name: target-${{ matrix.os }}-${{ matrix.java }}-${{ matrix.scala }}-${{ matrix.project }} path: targets.tar publish: @@ -125,27 +138,26 @@ jobs: if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/series/2.x') strategy: matrix: - os: [ubuntu-latest] - scala: [2.13.8] + os: [ubuntu-22.04] java: [temurin@8] runs-on: ${{ matrix.os }} steps: - name: Checkout current branch (full) - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Download Java (temurin@8) id: download-java-temurin-8 if: matrix.java == 'temurin@8' - uses: typelevel/download-java@v1 + uses: typelevel/download-java@v2 with: distribution: temurin java-version: 8 - name: Setup Java (temurin@8) if: matrix.java == 'temurin@8' - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: jdkfile java-version: 8 @@ -154,21 +166,21 @@ jobs: - name: Download Java (temurin@17) id: download-java-temurin-17 if: matrix.java == 'temurin@17' - uses: typelevel/download-java@v1 + uses: typelevel/download-java@v2 with: distribution: temurin java-version: 17 - name: Setup Java (temurin@17) if: matrix.java == 'temurin@17' - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: jdkfile java-version: 17 jdkFile: ${{ steps.download-java-temurin-17.outputs.jdkFile }} - name: Cache sbt - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ~/.sbt @@ -179,32 +191,92 @@ jobs: ~/Library/Caches/Coursier/v1 key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - name: Download target directories (2.12.16) - uses: actions/download-artifact@v2 + - name: Download target directories (2.12.18, rootJS) + uses: actions/download-artifact@v3 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.18-rootJS + + - name: Inflate target directories (2.12.18, rootJS) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (2.12.18, rootJVM) + uses: actions/download-artifact@v3 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.18-rootJVM + + - name: Inflate target directories (2.12.18, rootJVM) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (2.12.18, rootNative) + uses: actions/download-artifact@v3 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.18-rootNative + + - name: Inflate target directories (2.12.18, rootNative) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (3.3.0, rootJS) + uses: actions/download-artifact@v3 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-3.3.0-rootJS + + - name: Inflate target directories (3.3.0, rootJS) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (3.3.0, rootJVM) + uses: actions/download-artifact@v3 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-3.3.0-rootJVM + + - name: Inflate target directories (3.3.0, rootJVM) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (3.3.0, rootNative) + uses: actions/download-artifact@v3 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-3.3.0-rootNative + + - name: Inflate target directories (3.3.0, rootNative) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (2.13.11, rootJS) + uses: actions/download-artifact@v3 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.16 + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.11-rootJS - - name: Inflate target directories (2.12.16) + - name: Inflate target directories (2.13.11, rootJS) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (3.1.3) - uses: actions/download-artifact@v2 + - name: Download target directories (2.13.11, rootJVM) + uses: actions/download-artifact@v3 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-3.1.3 + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.11-rootJVM - - name: Inflate target directories (3.1.3) + - name: Inflate target directories (2.13.11, rootJVM) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (2.13.8) - uses: actions/download-artifact@v2 + - name: Download target directories (2.13.11, rootNative) + uses: actions/download-artifact@v3 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.8 + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.11-rootNative - - name: Inflate target directories (2.13.8) + - name: Inflate target directories (2.13.11, rootNative) run: | tar xf targets.tar rm targets.tar @@ -221,33 +293,32 @@ jobs: (echo "$PGP_PASSPHRASE"; echo; echo) | gpg --command-fd 0 --pinentry-mode loopback --change-passphrase $(gpg --list-secret-keys --with-colons 2> /dev/null | grep '^sec:' | cut --delimiter ':' --fields 5 | tail -n 1) - name: Publish - run: sbt '++${{ matrix.scala }}' tlRelease + run: sbt tlCiRelease site: name: Generate Site strategy: matrix: os: [ubuntu-latest] - scala: [2.13.8] java: [temurin@8] runs-on: ${{ matrix.os }} steps: - name: Checkout current branch (full) - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Download Java (temurin@8) id: download-java-temurin-8 if: matrix.java == 'temurin@8' - uses: typelevel/download-java@v1 + uses: typelevel/download-java@v2 with: distribution: temurin java-version: 8 - name: Setup Java (temurin@8) if: matrix.java == 'temurin@8' - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: jdkfile java-version: 8 @@ -256,21 +327,21 @@ jobs: - name: Download Java (temurin@17) id: download-java-temurin-17 if: matrix.java == 'temurin@17' - uses: typelevel/download-java@v1 + uses: typelevel/download-java@v2 with: distribution: temurin java-version: 17 - name: Setup Java (temurin@17) if: matrix.java == 'temurin@17' - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: jdkfile java-version: 17 jdkFile: ${{ steps.download-java-temurin-17.outputs.jdkFile }} - name: Cache sbt - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ~/.sbt @@ -282,11 +353,11 @@ jobs: key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - name: Generate site - run: sbt '++${{ matrix.scala }}' docs/tlSite + run: sbt docs/tlSite - name: Publish site if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' - uses: peaceiris/actions-gh-pages@v3.8.0 + uses: peaceiris/actions-gh-pages@v3.9.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: site/target/docs/site diff --git a/.jvmopts b/.jvmopts new file mode 100644 index 00000000..6f8a1a39 --- /dev/null +++ b/.jvmopts @@ -0,0 +1,3 @@ +-Xms1G +-Xmx4G +-XX:+UseG1GC \ No newline at end of file diff --git a/.scalafmt.conf b/.scalafmt.conf index 4f345799..84d3b61b 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,4 +1,4 @@ -version = 3.5.9 +version = 3.7.12 align.openParenCallSite = true align.openParenDefnSite = true maxColumn = 120 diff --git a/README.md b/README.md index 75592988..203e30c9 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Mouse includes enrichments for: - [Set](./shared/src/main/scala/mouse/set.scala) - [String](./shared/src/main/scala/mouse/string.scala) - [Try](./shared/src/main/scala/mouse/try.scala) -- [Tuple](./shared/src/main/scala-2.x/src/main/scala/mouse/tuple.scala) +- [Tuple](./shared/src/main/scala-2/src/main/scala/mouse/tuple.scala) #### Example: diff --git a/build.sbt b/build.sbt index 9e6b5455..ea336cd0 100644 --- a/build.sbt +++ b/build.sbt @@ -1,6 +1,6 @@ -val Scala212 = "2.12.16" -val Scala213 = "2.13.8" -val Scala3 = "3.1.3" +val Scala212 = "2.12.18" +val Scala213 = "2.13.11" +val Scala3 = "3.3.0" ThisBuild / organization := "org.typelevel" ThisBuild / organizationName := "Typelevel" @@ -10,24 +10,23 @@ ThisBuild / crossScalaVersions := Seq(Scala212, Scala3, Scala213) ThisBuild / tlVersionIntroduced := Map("3" -> "1.0.3") ThisBuild / tlCiReleaseBranches := Seq("series/2.x") ThisBuild / tlSiteApiUrl := Some(url("https://www.javadoc.io/doc/org.typelevel/mouse_2.13/latest")) +ThisBuild / githubWorkflowOSes := Seq("ubuntu-22.04") -lazy val root = project - .in(file(".")) +lazy val root = tlCrossRootProject .settings( name := "mouse", licenses := List(License.MIT) ) - .aggregate(js, jvm) - .enablePlugins(NoPublishPlugin) + .aggregate(cross) -lazy val cross = crossProject(JSPlatform, JVMPlatform) +lazy val cross = crossProject(JSPlatform, JVMPlatform, NativePlatform) .in(file(".")) .settings( name := "mouse", libraryDependencies ++= Seq( - "org.typelevel" %%% "cats-core" % "2.8.0", - "org.scalameta" %%% "munit" % "0.7.29" % Test, - "org.scalameta" %%% "munit-scalacheck" % "0.7.29" % Test + "org.typelevel" %%% "cats-core" % "2.10.0", + "org.scalameta" %%% "munit" % "1.0.0-M8" % Test, + "org.scalameta" %%% "munit-scalacheck" % "1.0.0-M8" % Test ), ThisBuild / licenses := List("MIT license" -> url("http://opensource.org/licenses/MIT")), developers := List( @@ -50,6 +49,9 @@ lazy val cross = crossProject(JSPlatform, JVMPlatform) .jsSettings( tlVersionIntroduced := Map("3" -> "1.0.13") ) + .nativeSettings( + tlVersionIntroduced := List("2.12", "2.13", "3").map(_ -> "1.2.0").toMap + ) lazy val docs = project .in(file("site")) @@ -63,6 +65,7 @@ ThisBuild / githubWorkflowJavaVersions := Seq(JDK8, JDK17) lazy val jvm = cross.jvm lazy val js = cross.js +lazy val native = cross.native // Scalafmt addCommandAlias("fmt", "; Compile / scalafmt; Test / scalafmt; scalafmtSbt") diff --git a/native/src/main/scala-2/mouse/mouse.scala b/native/src/main/scala-2/mouse/mouse.scala new file mode 100644 index 00000000..2a68b410 --- /dev/null +++ b/native/src/main/scala-2/mouse/mouse.scala @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 Typelevel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package object mouse extends MouseFunctions { + object all extends AllSharedSyntax + object any extends AnySyntax + object anyf extends AnyFSyntax + object boolean extends BooleanSyntax + object double extends DoubleSyntax + object fboolean extends FBooleanSyntax + object feither extends FEitherSyntax + object fnested extends FNestedSyntax + object foption extends FOptionSyntax + object ftuple extends FTupleSyntax + object int extends IntSyntax + object list extends ListSyntax + object long extends LongSyntax + object map extends MapSyntax + object option extends OptionSyntax + object set extends SetSyntax + object string extends StringSyntax + object `try` extends TrySyntax + object tuple extends TupleSyntax +} diff --git a/native/src/main/scala-3/mouse/package.scala b/native/src/main/scala-3/mouse/package.scala new file mode 100644 index 00000000..5e66858c --- /dev/null +++ b/native/src/main/scala-3/mouse/package.scala @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016 Typelevel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package object mouse extends MouseFunctions { + object all extends AllSharedSyntax + object any extends AnySyntax + object anyf extends AnyFSyntax + object boolean extends BooleanSyntax + object double extends DoubleSyntax + object fboolean extends FBooleanSyntax + object feither extends FEitherSyntax + object fnested extends FNestedSyntax + object foption extends FOptionSyntax + object ftuple extends FTupleSyntax + object int extends IntSyntax + object list extends ListSyntax + object long extends LongSyntax + object map extends MapSyntax + object option extends OptionSyntax + object set extends SetSyntax + object string extends StringSyntax + object `try` extends TrySyntax +} diff --git a/project/build.properties b/project/build.properties index 22af2628..52413ab7 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.7.1 +sbt.version=1.9.3 diff --git a/project/plugins.sbt b/project/plugins.sbt index dfe50477..91ecb3f4 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,6 @@ -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.10.1") -addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.2.0") -addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.4.13") -addSbtPlugin("org.typelevel" % "sbt-typelevel-site" % "0.4.13") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.13.2") +addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.2") +addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.14") +addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.3.2") +addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.4.22") +addSbtPlugin("org.typelevel" % "sbt-typelevel-site" % "0.4.22") diff --git a/shared/src/main/scala/mouse/MouseFunctions.scala b/shared/src/main/scala/mouse/MouseFunctions.scala index 23bb4a4a..09bedff7 100644 --- a/shared/src/main/scala/mouse/MouseFunctions.scala +++ b/shared/src/main/scala/mouse/MouseFunctions.scala @@ -32,6 +32,5 @@ trait MouseFunctions { * @param a * - the value to be evaluated and ignored. */ - def ignore(@nowarn a: Any): Unit = () - + def ignore(@nowarn a: Any): Unit = (): Unit } diff --git a/shared/src/main/scala/mouse/feither.scala b/shared/src/main/scala/mouse/feither.scala index c7317fe6..d18f76f7 100644 --- a/shared/src/main/scala/mouse/feither.scala +++ b/shared/src/main/scala/mouse/feither.scala @@ -90,6 +90,12 @@ final class FEitherOps[F[_], L, R](private val felr: F[Either[L, R]]) extends An case r @ Right(_) => r.asInstanceOf[Right[A, R]] } + def leftWidenIn[A >: L](implicit F: Functor[F]): F[Either[A, R]] = + F.map(felr) { + case l @ Left(_) => l.asInstanceOf[Left[A, R]] + case r @ Right(_) => r.asInstanceOf[Right[A, R]] + } + def leftTraverseIn[G[_], A](f: L => G[A])(implicit F: Functor[F], G: Applicative[G]): F[G[Either[A, R]]] = F.map(felr) { case Left(left) => G.map(f(left))(Left(_)) @@ -141,4 +147,9 @@ final class FEitherOps[F[_], L, R](private val felr: F[Either[L, R]]) extends An def liftEitherT: EitherT[F, L, R] = EitherT(felr) + def widenIn[A >: R](implicit F: Functor[F]): F[Either[L, A]] = + F.map(felr) { + case l @ Left(_) => l.asInstanceOf[Left[L, A]] + case r @ Right(_) => r.asInstanceOf[Right[L, A]] + } } diff --git a/shared/src/test/scala/mouse/FEitherSyntaxTest.scala b/shared/src/test/scala/mouse/FEitherSyntaxTest.scala index 0a9b0eea..b5aff066 100644 --- a/shared/src/test/scala/mouse/FEitherSyntaxTest.scala +++ b/shared/src/test/scala/mouse/FEitherSyntaxTest.scala @@ -45,6 +45,13 @@ class FEitherSyntaxTest extends MouseSuite { assertEquals(leftValue.flatMapIn(i => (i * 2).asRight[String]), leftValue) } + test("FEitherSyntax.leftWidenIn") { + val initial: Option[Either[List[Int], String]] = Option(List(1).asLeft[String]) + val expected: Option[Either[Seq[Int], String]] = Option(Seq(1).asLeft[String]) + + assertEquals(initial.leftWidenIn[Seq[Int]], expected) + } + test("FEitherSyntax.flatMapF") { assertEquals(rightValue.flatMapF(i => List((i * 2).asRight[String])), List(84.asRight[String])) assertEquals(leftValue.flatMapF(i => List((i * 2).asRight[String])), leftValue) @@ -168,4 +175,11 @@ class FEitherSyntaxTest extends MouseSuite { assertEquals(List(42.asRight[Int]).mergeIn, List(42)) assertEquals(List("42".asLeft[String]).mergeIn, List("42")) } + + test("FEitherSyntax.widenIn") { + val initial: Option[Either[String, List[Int]]] = Option(List(1).asRight[String]) + val expected: Option[Either[String, Seq[Int]]] = Option(Seq(1).asRight[String]) + + assertEquals(initial.widenIn[Seq[Int]], expected) + } } diff --git a/shared/src/test/scala/mouse/StringSyntaxTests.scala b/shared/src/test/scala/mouse/StringSyntaxTests.scala index b17df133..0361ba04 100644 --- a/shared/src/test/scala/mouse/StringSyntaxTests.scala +++ b/shared/src/test/scala/mouse/StringSyntaxTests.scala @@ -29,7 +29,9 @@ import org.scalacheck.{Arbitrary, Gen} class StringSyntaxTests extends MouseSuite { test("StringOps.parseInt") { assertEquals("123".parseInt, 123.asRight[NumberFormatException]) - assertEquals("blah".parseInt.leftMap(_.getMessage), "For input string: \"blah\"".asLeft) + assertEquals("blah".parseInt.leftMap(_.getMessage.replace("string ", "string: ")), + "For input string: \"blah\"".asLeft + ) } property("scalacheck-suite: StringOps.parseInt") { @@ -48,7 +50,9 @@ class StringSyntaxTests extends MouseSuite { test("StringOps.parseLong") { assertEquals("123".parseLong, 123L.asRight[NumberFormatException]) - assertEquals("blah".parseLong.leftMap(_.getMessage), "For input string: \"blah\"".asLeft) + assertEquals("blah".parseLong.leftMap(_.getMessage.replace("string ", "string: ")), + "For input string: \"blah\"".asLeft + ) } property("scalacheck-suite: StringOps.parseLong") { @@ -67,7 +71,9 @@ class StringSyntaxTests extends MouseSuite { test("StringOps.parseShort") { assertEquals("123".parseShort, 123.toShort.asRight[NumberFormatException]) - assertEquals("blah".parseShort.leftMap(_.getMessage), "For input string: \"blah\"".asLeft) + assertEquals("blah".parseShort.leftMap(_.getMessage.replace("string ", "string: ")), + "For input string: \"blah\"".asLeft + ) } property("scalacheck-suite: StringOps.parseShort") { @@ -86,7 +92,9 @@ class StringSyntaxTests extends MouseSuite { test("StringOps.parseDouble") { assertEquals("123.1".parseDouble, 123.1.asRight[NumberFormatException]) - assertEquals("blah".parseDouble.leftMap(_.getMessage), "For input string: \"blah\"".asLeft) + assertEquals("blah".parseDouble.leftMap(_.getMessage.replace("string ", "string: ")), + "For input string: \"blah\"".asLeft + ) } property("scalacheck-suite: StringOps.parseDouble") { @@ -104,7 +112,9 @@ class StringSyntaxTests extends MouseSuite { } test("StringOps.parseFloat") { - assertEquals("blah".parseFloat.leftMap(_.getMessage), "For input string: \"blah\"".asLeft) + assertEquals("blah".parseFloat.leftMap(_.getMessage.replace("string ", "string: ")), + "For input string: \"blah\"".asLeft + ) } property("scalacheck-suite: StringOps.parseFloat") { @@ -123,7 +133,9 @@ class StringSyntaxTests extends MouseSuite { test("StringOps.parseByte") { assertEquals("123".parseByte, 123.toByte.asRight[NumberFormatException]) - assertEquals("blah".parseByte.leftMap(_.getMessage), "For input string: \"blah\"".asLeft) + assertEquals("blah".parseByte.leftMap(_.getMessage.replace("string ", "string: ")), + "For input string: \"blah\"".asLeft + ) } property("scalacheck-suite: StringOps.parseByte") { @@ -142,7 +154,9 @@ class StringSyntaxTests extends MouseSuite { test("StringOps.parseBigInt") { assertEquals("123".parseBigInt, BigInt("123").asRight[NumberFormatException]) - assertEquals("blah".parseBigInt.leftMap(_.getMessage), "For input string: \"blah\"".asLeft) + assertEquals("blah".parseBigInt.leftMap(_.getMessage.replace("string ", "string: ")), + "For input string: \"blah\"".asLeft + ) } property("scalacheck-suite: StringOps.parseBigInt") { @@ -196,7 +210,9 @@ class StringSyntaxTests extends MouseSuite { Arbitrary.arbString.arbitrary.filter(s => !s.equalsIgnoreCase("true") && !s.equalsIgnoreCase("false")) forAll(stringGen) { (s: String) => - assertEquals(s.parseBoolean.leftMap(_.getMessage), ("For input string: \"" + s + "\"").asLeft) + assertEquals(s.parseBoolean.leftMap(_.getMessage.replace("string ", "string: ")), + ("For input string: \"" + s + "\"").asLeft + ) } }