Skip to content

Commit

Permalink
Support sbt-typelevel and sbt-crossproject (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
zainab-ali authored Aug 30, 2024
1 parent 7cbedba commit c7dcf85
Show file tree
Hide file tree
Showing 19 changed files with 237 additions and 12 deletions.
8 changes: 0 additions & 8 deletions docs/markdown/limitations.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@ This page is a shortlist of the known limitations of snapshot4s. If you encounte

`snapshot4s` doesn't yet support Scala Native.

## `sbt-crossproject` is not supported

`snapshot4s` doesn't yet support the `CrossType.Pure` project layout of `sbt-crossproject`. This means that projects using `sbt-typelevel` are also not supported.

It should support all other project layouts, such as `sbt-projectmatrix`.

Support for `sbt-crossproject` is [on our roadmap](https://github.com/siriusxm/snapshot4s/issues/28).

## Promoted code may fail to compile with `not found` errors

`snapshot4s` uses `pprint` to efficiently generate the source code corresponding to an expected value. This doesn’t add import statements for `enum` and classes within objects. You may need to add an import statement corresponding to the `enum` or object in question.
Expand Down
38 changes: 36 additions & 2 deletions docs/markdown/sbt-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ You can enable `snapshot4s` for a variety of SBT project layouts.
- For single project SBT builds follow [these instructions](#single-project-builds).
- For multi-project SBT builds follow [these instructions](#multi-project-builds)
- For `sbt-projectmatrix` follow [these instructions](#sbt-projectmatrix).

snapshot4s does not yet support `sbt-crossproject` or `sbt-typelevel`. These are [on our roadmap](https://github.com/siriusxm/snapshot4s/issues/28).
- For `sbt-crossproject` and `sbt-typelevel` follow [these instructions](#sbt-crossproject-and-sbt-typelevel).

## Single project builds

Expand Down Expand Up @@ -55,3 +54,38 @@ val core = (projectMatrix in file("core")).enablePlugins(Snapshot4sPlugin)
```

Finally, add the integration library for your [test framework](./supported-frameworks.md).

## sbt-crossproject and sbt-typelevel

You can enable the plugin for all cross types, for both JVM and JS.

Add the plugin to `plugins.sbt`.

```scala
addSbtPlugin("com.siriusxm" % "sbt-snapshot4s" % "@LATEST_STABLE_VERSION@")
```

Enable the plugin.

```scala
val core = crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Dummy)
.in(file("core"))
.enablePlugins(Snapshot4sPlugin)
```

If you use the `Pure` or `Full` cross types, set the `snapshot4sResourceDirectory` to the shared test resource directory.

```scala
val core = crossProject(JVMPlatform)
.crossType(CrossType.Pure)
.in(file("core"))
.settings(
snapshot4sResourceDirectory := CrossType.Pure
.sharedResourcesDir(baseDirectory.value, "test")
.get / "snapshot",
)
.enablePlugins(Snapshot4sPlugin)
```

Finally, add the integration library for your [test framework](./supported-frameworks.md).
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ object generated {
implicit val snapshotConfig: SnapshotConfig = new SnapshotConfig(
resourceDirectory = Path("${snapshot4sResourceDirectory.value}"),
outputDirectory = Path("${snapshot4sDirectory.value}"),
sourceDirectory = Path("${(Test / sourceDirectory).value}")
sourceDirectory = Path("${sourceBaseDirectory((Test / sourceDirectories).value)}")
)
}
"""
Expand All @@ -71,11 +71,20 @@ object generated {
)
applyInlinePatches(log)(
snapshot4sDirectory.value / "inline-patch",
(Test / sourceDirectory).value
sourceBaseDirectory((Test / sourceDirectories).value)
)
}
)

private def sourceBaseDirectory(sourceDirectories: Seq[File]): File = {
def sharedParent(dirA: File, dirB: File): File = {
if (dirB.getAbsolutePath().startsWith(dirA.getAbsolutePath())) dirA
else if (dirA.getAbsolutePath().startsWith(dirB.getAbsolutePath())) dirB
else sharedParent(dirA.getParentFile, dirB)
}
sourceDirectories.reduce(sharedParent)
}

private def applyResourcePatches(log: Logger)(resourcePatchDir: File, resourceDir: File) = {
val patches = (resourcePatchDir ** (-DirectoryFilter)).get
patches.foreach { patchFile =>
Expand Down
47 changes: 47 additions & 0 deletions modules/plugin/src/sbt-test/sbt-snapshot4s/sbt-typelevel/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import snapshot4s.BuildInfo.snapshot4sVersion

val Scala3 = "3.3.0"
ThisBuild / crossScalaVersions := Seq("2.13.11", Scala3)
ThisBuild / scalaVersion := Scala3
ThisBuild / tlBaseVersion := "0.4"
lazy val root = tlCrossRootProject.aggregate(core, utils)

lazy val core = crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Pure)
.in(file("core"))
.settings(
name := "core",
snapshot4sResourceDirectory := CrossType.Pure
.sharedResourcesDir(baseDirectory.value, "test")
.get / "snapshot",
testFrameworks += new TestFramework("weaver.framework.CatsEffect"),
Test / scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) },
libraryDependencies += "com.siriusxm" %%% "snapshot4s-weaver" % snapshot4sVersion % Test
)
.enablePlugins(Snapshot4sPlugin)

lazy val utils = crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Full)
.in(file("utils"))
.settings(
name := "utils",
snapshot4sResourceDirectory := CrossType.Full
.sharedResourcesDir(baseDirectory.value, "test")
.get / "snapshot",
Test / scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) },
testFrameworks += new TestFramework("weaver.framework.CatsEffect"),
libraryDependencies += "com.siriusxm" %%% "snapshot4s-weaver" % snapshot4sVersion % Test
)
.enablePlugins(Snapshot4sPlugin)

lazy val framework = crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Full)
.in(file("framework"))
.settings(
name := "framework",
Test / scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) },
testFrameworks += new TestFramework("weaver.framework.CatsEffect"),
libraryDependencies += "com.siriusxm" %%% "snapshot4s-weaver" % snapshot4sVersion % Test
)
.enablePlugins(Snapshot4sPlugin)

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
old-contents
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
old-contents
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package simple

import weaver._
import snapshot4s.weaver.SnapshotExpectations
import snapshot4s.generated.snapshotConfig

object SimpleTest extends SimpleIOSuite with SnapshotExpectations {

test("inline") {
assertInlineSnapshot(1, 2)
}

test("new inline snapshot") {
assertInlineSnapshot(1, ???)
}

test("file that doesn't exist") {
assertFileSnapshot("contents", "nonexistent-file")
}

test("existing file") {
assertFileSnapshot("contents", "existing-file")
}

test("file in nested directory") {
assertFileSnapshot("contents", "nested-directory/nested-file")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
old-contents
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
old-contents
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package simple

import weaver._
import snapshot4s.weaver.SnapshotExpectations
import snapshot4s.generated.snapshotConfig

object SimpleTest extends SimpleIOSuite with SnapshotExpectations {

test("inline") {
assertInlineSnapshot(1, 2)
}

test("new inline snapshot") {
assertInlineSnapshot(1, ???)
}

test("file that doesn't exist") {
assertFileSnapshot("contents", "nonexistent-file")
}

test("existing file") {
assertFileSnapshot("contents", "existing-file")
}

test("file in nested directory") {
assertFileSnapshot("contents", "nested-directory/nested-file")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
old-contents
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
old-contents
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package simple

import weaver._
import snapshot4s.weaver.SnapshotExpectations
import snapshot4s.generated.snapshotConfig

object SimpleTest extends SimpleIOSuite with SnapshotExpectations {

test("inline") {
assertInlineSnapshot(1, 2)
}

test("new inline snapshot") {
assertInlineSnapshot(1, ???)
}

test("file that doesn't exist") {
assertFileSnapshot("contents", "nonexistent-file")
}

test("existing file") {
assertFileSnapshot("contents", "existing-file")
}

test("file in nested directory") {
assertFileSnapshot("contents", "nested-directory/nested-file")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.10.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.7.2")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")

sys.props.get("plugin.version") match {
case Some(x) =>
addSbtPlugin("com.siriusxm" % "sbt-snapshot4s" % x)
case _ =>
sys.error("""|The system property 'plugin.version' is not defined.
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
}
8 changes: 8 additions & 0 deletions modules/plugin/src/sbt-test/sbt-snapshot4s/sbt-typelevel/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Generated code should link
> Test / compile
# Tests should fail as snapshots are out of date
-> Test / test
# Update snapshots
> snapshot4sPromote
# Tests should succeed with updated snapshots
> Test / test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
old-contents
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
old-contents
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package simple

import weaver._
import snapshot4s.weaver.SnapshotExpectations
import snapshot4s.generated.snapshotConfig

object SimpleTest extends SimpleIOSuite with SnapshotExpectations {

test("inline") {
assertInlineSnapshot(1, 2)
}

test("new inline snapshot") {
assertInlineSnapshot(1, ???)
}

test("file that doesn't exist") {
assertFileSnapshot("contents", "nonexistent-file")
}

test("existing file") {
assertFileSnapshot("contents", "existing-file")
}

test("file in nested directory") {
assertFileSnapshot("contents", "nested-directory/nested-file")
}

}

0 comments on commit c7dcf85

Please sign in to comment.