diff --git a/docs/markdown/faq.md b/docs/markdown/faq.md index 6c28928..c66541c 100644 --- a/docs/markdown/faq.md +++ b/docs/markdown/faq.md @@ -18,3 +18,7 @@ Unlike `circe-golden`, snapshot4s is aimed at broader example-based testing. It Here are a few tools for other languages: - The [Jest Javascript testing framework](https://jestjs.io/docs/snapshot-testing) supports snapshot testing. - [Insta.rs](https://insta.rs/) is a snapshot testing tool for Rust. + +## Can I choose to promote snapshots only in selected file? + +Yes! Similarly to running only specific test with `testOnly *MySuite*` sbt command, you can use `snapshot4sPromote *MySuite*` to only update the snapshots present in and referenced by `MySuite.scala`. diff --git a/modules/core/src/main/scala-2/com/siriusxm/snapshot4s/AssertFileSnapshotMacro.scala b/modules/core/src/main/scala-2/com/siriusxm/snapshot4s/AssertFileSnapshotMacro.scala new file mode 100644 index 0000000..c406272 --- /dev/null +++ b/modules/core/src/main/scala-2/com/siriusxm/snapshot4s/AssertFileSnapshotMacro.scala @@ -0,0 +1,71 @@ +/* + * Copyright 2024 SiriusXM + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package snapshot4s + +import scala.reflect.macros.blackbox + +private[snapshot4s] trait AssertFileSnapshotMacro[R] { + + /** Assert that a found value is equal to a previously snapshotted value. + * + * If the assertion fails, the file can be recreated with the found contents using `snapshot4sPromote`. + * @see https://siriusxm.github.io/snapshot4s/file-snapshots + * + * @param found The found value. + * @param snapshotPath Path to file containing the previously snapshotted value. This is relative to the resources/snapshot directory. + * @param eq Compares the found and snapshot values. + * @param resultLike Constructs a framework-specific result. + */ + def assertFileSnapshot(found: String, snapshotPath: String)(implicit + config: SnapshotConfig, + snapshotEq: SnapshotEq[String], + resultLike: ResultLike[String, R] + ): R = macro AssertFileSnapshotMacro.Macro.impl[R] +} + +private[snapshot4s] object AssertFileSnapshotMacro { + + class Macro(val c: blackbox.Context) { + import c.universe.* + + def impl[E]( + found: Expr[String], + snapshotPath: Expr[String] + )( + config: Expr[SnapshotConfig], + snapshotEq: Expr[SnapshotEq[String]], + resultLike: Expr[ResultLike[String, E]] + ): Tree = { + // Scala 2 macro system will place this call in client code so the called method must be public + // `FileSnapshotProxy.createFileSnapshot` is introduced to keep `FileSnapshot` private + q"""_root_.snapshot4s.FileSnapshotProxy.createFileSnapshot($found, $snapshotPath, ${c.enclosingPosition.source.path}, $config, $snapshotEq, $resultLike)""" + } + } + +} + +object FileSnapshotProxy { + + def createFileSnapshot[E]( + found: String, + snapshotPath: String, + sourceFile: String, + config: SnapshotConfig, + snapshotEq: SnapshotEq[String], + resultLike: ResultLike[String, E] + ): E = FileSnapshot(found, snapshotPath, sourceFile, config, snapshotEq, resultLike) +} diff --git a/modules/core/src/main/scala-3/com/siriusxm/snapshot4s/AssertFileSnapshotMacro.scala b/modules/core/src/main/scala-3/com/siriusxm/snapshot4s/AssertFileSnapshotMacro.scala new file mode 100644 index 0000000..3d7ab33 --- /dev/null +++ b/modules/core/src/main/scala-3/com/siriusxm/snapshot4s/AssertFileSnapshotMacro.scala @@ -0,0 +1,61 @@ +/* + * Copyright 2024 SiriusXM + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package snapshot4s + +private[snapshot4s] trait AssertFileSnapshotMacro[R]: + + /** Assert that a found value is equal to a previously snapshotted value. + * + * If the assertion fails, the file can be recreated with the found contents using `snapshot4sPromote`. + * @see https://siriusxm.github.io/snapshot4s/file-snapshots + * + * @param found The found value. + * @param snapshotPath Path to file containing the previously snapshotted value. This is relative to the resources/snapshot directory. + * @param eq Compares the found and snapshot values. + * @param resultLike Constructs a framework-specific result. + */ + inline def assertFileSnapshot(found: String, snapshotPath: String)(implicit + config: SnapshotConfig, + eq: SnapshotEq[String], + resultLike: ResultLike[String, R] + ): R = + ${ + AssertFileSnapshotMacro.impl( + 'found, + 'snapshotPath, + 'config, + 'eq, + 'resultLike + ) + } + +import scala.quoted.* + +private[snapshot4s] object AssertFileSnapshotMacro: + + def impl[A, E]( + found: Expr[String], + snapshotPath: Expr[String], + config: Expr[SnapshotConfig], + snapshotEq: Expr[SnapshotEq[String]], + resultLike: Expr[ResultLike[String, E]] + )(using q: Quotes, ta: Type[A], te: Type[E]): Expr[E] = + import q.reflect.* + val sourceFile = Expr(Position.ofMacroExpansion.sourceFile.path) + '{ + FileSnapshot($found, $snapshotPath, $sourceFile, $config, $snapshotEq, $resultLike) + } diff --git a/modules/core/src/main/scala/com/siriusxm/snapshot4s/FileSnapshot.scala b/modules/core/src/main/scala/com/siriusxm/snapshot4s/FileSnapshot.scala index fe3a260..7e95f36 100644 --- a/modules/core/src/main/scala/com/siriusxm/snapshot4s/FileSnapshot.scala +++ b/modules/core/src/main/scala/com/siriusxm/snapshot4s/FileSnapshot.scala @@ -21,13 +21,16 @@ private[snapshot4s] object FileSnapshot { def apply[E]( found: String, snapshotPath: String, + sourceFile: String, config: SnapshotConfig, eq: SnapshotEq[String], resultLike: ResultLike[String, E] ): E = resultLike { () => + val relativePath = Locations.relativeSourceFilePath(sourceFile, config) val absoluteSnapshotPath = config.resourceDirectory / RelPath(snapshotPath) def writePatchFile() = { - val patchPath = config.outputDirectory / RelPath("resource-patch") / RelPath(snapshotPath) + val patchPath = + config.outputDirectory / RelPath("resource-patch") / relativePath / RelPath(snapshotPath) patchPath.write(found) } if (absoluteSnapshotPath.exists()) { @@ -43,4 +46,5 @@ private[snapshot4s] object FileSnapshot { Result.NonExistent(found) } } + } diff --git a/modules/core/src/main/scala/com/siriusxm/snapshot4s/InlineSnapshot.scala b/modules/core/src/main/scala/com/siriusxm/snapshot4s/InlineSnapshot.scala index 48c6b9d..3d60d14 100644 --- a/modules/core/src/main/scala/com/siriusxm/snapshot4s/InlineSnapshot.scala +++ b/modules/core/src/main/scala/com/siriusxm/snapshot4s/InlineSnapshot.scala @@ -75,7 +75,7 @@ object InlineSnapshot { val sourceFileHash = Hashing.calculateHash(sourceFileContent) val hashHeader = Hashing.produceHashHeader(sourceFileHash) val changeFile = - config.outputDirectory / RelPath("inline-patch") / relativeSourceFilePath( + config.outputDirectory / RelPath("inline-patch") / Locations.relativeSourceFilePath( sourceFile, config ) / RelPath(s"$startPosition-$endPosition") @@ -84,17 +84,6 @@ object InlineSnapshot { changeFile.write(actualStr) } - private[snapshot4s] def relativeSourceFilePath( - sourceFile: String, - config: SnapshotConfig - ): RelPath = { - val baseDirectory = config.sourceDirectory - val sourceFilePath = Path(sourceFile) - sourceFilePath.relativeTo(baseDirectory).getOrElse { - throw new SnapshotConfigUnsupportedError(config) - } - } - // See the Scala 2.13 compiler for the source of the warning we're ignoring: // https://github.com/scala/scala/blob/2.13.x/src/compiler/scala/tools/nsc/typechecker/Typers.scala#L118 private final val InterpolatorCodeRegex = """\$\{\s*(.*?)\s*\}""".r diff --git a/modules/core/src/main/scala/com/siriusxm/snapshot4s/Locations.scala b/modules/core/src/main/scala/com/siriusxm/snapshot4s/Locations.scala new file mode 100644 index 0000000..7ba2abd --- /dev/null +++ b/modules/core/src/main/scala/com/siriusxm/snapshot4s/Locations.scala @@ -0,0 +1,32 @@ +/* + * Copyright 2024 SiriusXM + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package snapshot4s + +private[snapshot4s] object Locations { + + private[snapshot4s] def relativeSourceFilePath( + sourceFile: String, + config: SnapshotConfig + ): RelPath = { + val baseDirectory = config.sourceDirectory + val sourceFilePath = Path(sourceFile) + sourceFilePath.relativeTo(baseDirectory).getOrElse { + throw new SnapshotConfigUnsupportedError(config) + } + } + +} diff --git a/modules/core/src/main/scala/com/siriusxm/snapshot4s/SnapshotAssertions.scala b/modules/core/src/main/scala/com/siriusxm/snapshot4s/SnapshotAssertions.scala index c98cf96..1832cbb 100644 --- a/modules/core/src/main/scala/com/siriusxm/snapshot4s/SnapshotAssertions.scala +++ b/modules/core/src/main/scala/com/siriusxm/snapshot4s/SnapshotAssertions.scala @@ -20,22 +20,4 @@ package snapshot4s * * @tparam R Assertion result type specific to the test framework. For example, weaver's result type is `IO[Expectations]`. */ -trait SnapshotAssertions[R] extends AssertInlineSnapshotMacro[R] { - - /** Assert that a found value is equal to a previously snapshotted value. - * - * If the assertion fails, the file can be recreated with the found contents using `snapshot4sPromote`. - * @see https://siriusxm.github.io/snapshot4s/file-snapshots - * - * @param found The found value. - * @param snapshotPath Path to file containing the previously snapshotted value. This is relative to the resources/snapshot directory. - * @param eq Compares the found and snapshot values. - * @param resultLike Constructs a framework-specific result. - */ - def assertFileSnapshot(found: String, snapshotPath: String)(implicit - config: SnapshotConfig, - eq: SnapshotEq[String], - resultLike: ResultLike[String, R] - ): R = FileSnapshot(found, snapshotPath, config, eq, resultLike) - -} +trait SnapshotAssertions[R] extends AssertInlineSnapshotMacro[R] with AssertFileSnapshotMacro[R] diff --git a/modules/core/src/test/scala/com/siriusxm/snapshot4s/InlineSnapshotSpec.scala b/modules/core/src/test/scala/com/siriusxm/snapshot4s/LocationsSpec.scala similarity index 88% rename from modules/core/src/test/scala/com/siriusxm/snapshot4s/InlineSnapshotSpec.scala rename to modules/core/src/test/scala/com/siriusxm/snapshot4s/LocationsSpec.scala index 3b71321..c9a940e 100644 --- a/modules/core/src/test/scala/com/siriusxm/snapshot4s/InlineSnapshotSpec.scala +++ b/modules/core/src/test/scala/com/siriusxm/snapshot4s/LocationsSpec.scala @@ -19,7 +19,7 @@ package snapshot4s import cats.effect.IO import weaver.* -object InlineSnapshotSpec extends SimpleIOSuite { +object LocationsSpec extends SimpleIOSuite { pureTest("calculates relative paths correctly") { val config = new SnapshotConfig( @@ -28,7 +28,7 @@ object InlineSnapshotSpec extends SimpleIOSuite { sourceDirectory = Path("/path/to/sources") ) val relativePath = - InlineSnapshot.relativeSourceFilePath("/path/to/sources/TestFile.scala", config) + Locations.relativeSourceFilePath("/path/to/sources/TestFile.scala", config) expect.eql(relativePath.value, "TestFile.scala") } @@ -39,7 +39,7 @@ object InlineSnapshotSpec extends SimpleIOSuite { sourceDirectory = Path("/wrong/path/to/sources") ) val result = - IO(InlineSnapshot.relativeSourceFilePath("/path/to/sources/TestFile.scala", config)) + IO(Locations.relativeSourceFilePath("/path/to/sources/TestFile.scala", config)) val message = """Your project setup is not supported by snapshot4s. We encourage you to raise an issue at https://github.com/siriusxm/snapshot4s/issues/new?template=bug.md @@ -55,4 +55,5 @@ We have detected the following configuration: } } + } diff --git a/modules/core/src/test/scalajvm/com/siriusxm/snapshot4s/FileSnapshotSpec.scala b/modules/core/src/test/scalajvm/com/siriusxm/snapshot4s/FileSnapshotSpec.scala index 9f98c19..550d9e1 100644 --- a/modules/core/src/test/scalajvm/com/siriusxm/snapshot4s/FileSnapshotSpec.scala +++ b/modules/core/src/test/scalajvm/com/siriusxm/snapshot4s/FileSnapshotSpec.scala @@ -41,7 +41,14 @@ object FileSnapshotSpec extends SimpleIOSuite { } private def assert(found: String, path: PathChunk)(config: SnapshotConfig) = { - FileSnapshot(found, path.toString, config, comparison, resultLike) + FileSnapshot( + found, + path.toString, + s"${config.sourceDirectory.value}/src/test/scala/FileSnapshotSpec.scala", + config, + comparison, + resultLike + ) } private def writeSnapshot(snapshot: String, path: PathChunk)(config: SnapshotConfig) = { @@ -94,7 +101,9 @@ object FileSnapshotSpec extends SimpleIOSuite { patches <- getPatches(config) } yield expect.same( patches, - List(config.outputDirectory.osPath / "resource-patch" / "snapshot") + List( + config.outputDirectory.osPath / "resource-patch" / "src" / "test" / "scala" / "FileSnapshotSpec.scala" / "snapshot" + ) ) } @@ -105,7 +114,9 @@ object FileSnapshotSpec extends SimpleIOSuite { patches <- getPatches(config) } yield expect.same( patches, - List(config.outputDirectory.osPath / "resource-patch" / "nested" / "snapshot") + List( + config.outputDirectory.osPath / "resource-patch" / "src" / "test" / "scala" / "FileSnapshotSpec.scala" / "nested" / "snapshot" + ) ) } } diff --git a/modules/plugin/src/main/scala/com/siriusxm/snapshot/Snapshot4sPlugin.scala b/modules/plugin/src/main/scala/com/siriusxm/snapshot/Snapshot4sPlugin.scala index b6e9b07..b600427 100644 --- a/modules/plugin/src/main/scala/com/siriusxm/snapshot/Snapshot4sPlugin.scala +++ b/modules/plugin/src/main/scala/com/siriusxm/snapshot/Snapshot4sPlugin.scala @@ -18,6 +18,7 @@ package snapshot4s import sbt.* import sbt.Keys.* +import sbt.complete.DefaultParsers.* import sbt.util.Logger object Snapshot4sPlugin extends AutoPlugin { @@ -29,7 +30,7 @@ object Snapshot4sPlugin extends AutoPlugin { settingKey[File]("The directory in which snapshot4s results are stored prior to promotion.") val snapshot4sSourceGenerator = taskKey[Seq[File]]("Generate source files for snapshot4s testing.") - val snapshot4sPromote = taskKey[Unit]("Update failing snapshot4s snapshot files.") + val snapshot4sPromote = inputKey[Unit]("Update failing snapshot4s snapshot files.") } import autoImport.* @@ -65,17 +66,29 @@ object generated { }, snapshot4sPromote := { val log = streams.value.log + val arguments = + spaceDelimited("") + .examples("*MySuite*", "*MySuite.scala") + .parsed + + val filter = makeFilter(arguments) applyResourcePatches(log)( snapshot4sDirectory.value / "resource-patch", - snapshot4sResourceDirectory.value + snapshot4sResourceDirectory.value, + filter ) applyInlinePatches(log)( snapshot4sDirectory.value / "inline-patch", - sourceBaseDirectory((Test / sourceDirectories).value) + sourceBaseDirectory((Test / sourceDirectories).value), + filter ) } ) + private def makeFilter(arguments: Seq[String]): NameFilter = + if (arguments.isEmpty) AllPassFilter + else arguments.map(GlobFilter(_)).reduce(_ | _) + private def sourceBaseDirectory(sourceDirectories: Seq[File]): File = { def sharedParent(dirA: File, dirB: File): File = { if (dirB.getAbsolutePath().startsWith(dirA.getAbsolutePath())) dirA @@ -85,22 +98,34 @@ object generated { sourceDirectories.reduce(sharedParent) } - private def applyResourcePatches(log: Logger)(resourcePatchDir: File, resourceDir: File) = { - val patches = (resourcePatchDir ** (-DirectoryFilter)).get - patches.foreach { patchFile => - val patchContents = IO.read(patchFile) - val relativeSourceFile = IO.relativize(resourcePatchDir, patchFile).get - val sourceFile = resourceDir / relativeSourceFile + private def applyResourcePatches( + log: Logger + )(resourcePatchDir: File, resourceDir: File, filter: NameFilter) = { + val patches = (resourcePatchDir ** (-DirectoryFilter)).get + val filteredPatches = patches.filter(file => filter.accept(file.getParent)) + filteredPatches.foreach { patchFile => + val patchContents = IO.read(patchFile) + val sourceFile = locateResourceFile(resourcePatchDir, patchFile, resourceDir) IO.delete(patchFile) IO.write(sourceFile, patchContents) log.info(s"Patch applied to $sourceFile") } } - private def applyInlinePatches(log: Logger)(inlinePatchDir: File, sourceDir: File) = { - val allChangeFiles = (inlinePatchDir ** (-DirectoryFilter)).get + private def locateResourceFile(resourcePatchDir: File, patchFile: File, resourceDir: File) = { + val relativePath = + IO.relativize(resourcePatchDir, patchFile).get + // relative path starts with subpath like "src/test/scala/MyTest.scala" we need to remove that + val withoutSourceTestFileName = relativePath.split("\\.scala/").tail.mkString("/") + resourceDir / withoutSourceTestFileName + } - allChangeFiles.groupBy(_.getParent).foreach { case (parentDir, changeFiles) => + private def applyInlinePatches( + log: Logger + )(inlinePatchDir: File, sourceDir: File, filter: NameFilter) = { + val patchDirectories = (inlinePatchDir ** (-DirectoryFilter)).get + val dirsByParent = patchDirectories.groupBy(_.getParent).filterKeys(filter.accept) + dirsByParent.foreach { case (parentDir, changeFiles) => val relativeSourceFile = IO.relativize(inlinePatchDir, new File(parentDir)).get val sourceFile = sourceDir / relativeSourceFile val sourceContents = IO.read(sourceFile) diff --git a/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/build.sbt b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/build.sbt new file mode 100644 index 0000000..027c579 --- /dev/null +++ b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/build.sbt @@ -0,0 +1,10 @@ +import snapshot4s.BuildInfo.snapshot4sVersion + +lazy val root = (project in file(".")) + .settings( + scalaVersion := "3.3.1", + scalacOptions += "-Xsource:3", + crossScalaVersions := Seq("3.3.1", "2.12.20", "2.13.14"), + libraryDependencies += "com.siriusxm" %% "snapshot4s-weaver" % snapshot4sVersion % Test + ) + .enablePlugins(Snapshot4sPlugin) diff --git a/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/project/plugins.sbt b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/project/plugins.sbt new file mode 100644 index 0000000..8c23346 --- /dev/null +++ b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/project/plugins.sbt @@ -0,0 +1,6 @@ +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) +} diff --git a/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/src/test/resources/snapshot/existing-file b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/src/test/resources/snapshot/existing-file new file mode 100644 index 0000000..e33be70 --- /dev/null +++ b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/src/test/resources/snapshot/existing-file @@ -0,0 +1 @@ +old-contents diff --git a/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/src/test/resources/snapshot/nested-directory/nested-file b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/src/test/resources/snapshot/nested-directory/nested-file new file mode 100644 index 0000000..e33be70 --- /dev/null +++ b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/src/test/resources/snapshot/nested-directory/nested-file @@ -0,0 +1 @@ +old-contents diff --git a/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/src/test/scala/FilterTest.scala b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/src/test/scala/FilterTest.scala new file mode 100644 index 0000000..34130e7 --- /dev/null +++ b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/src/test/scala/FilterTest.scala @@ -0,0 +1,29 @@ +package simple + +import weaver.* +import snapshot4s.weaver.SnapshotExpectations +import snapshot4s.generated.snapshotConfig + +object FilterTest 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") + } + +} diff --git a/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/src/test/scala/OtherTest.scala b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/src/test/scala/OtherTest.scala new file mode 100644 index 0000000..6c5edcf --- /dev/null +++ b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/src/test/scala/OtherTest.scala @@ -0,0 +1,29 @@ +package simple + +import weaver.* +import snapshot4s.weaver.SnapshotExpectations +import snapshot4s.generated.snapshotConfig + +object OtherTest extends SimpleIOSuite with SnapshotExpectations { + + test("inline") { + assertInlineSnapshot(123, 456) + } + + test("new inline snapshot") { + assertInlineSnapshot(1, ???) + } + + test("file that doesn't exist") { + assertFileSnapshot("other-contents", "other-nonexistent-file") + } + + test("existing file") { + assertFileSnapshot("contents", "existing-file") + } + + test("file in nested directory") { + assertFileSnapshot("contents", "nested-directory/nested-file") + } + +} diff --git a/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/test b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/test new file mode 100644 index 0000000..bfcf848 --- /dev/null +++ b/modules/plugin/src/sbt-test/sbt-snapshot4s/promote-filter/test @@ -0,0 +1,23 @@ +# Generated code should compile +> ++ 2.12 compile +> ++ 2.13 compile +> ++ 3 compile +# # Tests should fail as snapshots are out of date +-> ++ 2.12 test +-> ++ 2.13 test +-> ++ 3 test +# Not update anything with invalid filter +> snapshot4sPromote *IDontExist* +# Tests should fail as snapshots are out of date +-> ++ 2.12 test +-> ++ 2.13 test +-> ++ 3 test +# # Update snapshots with correct filter +> snapshot4sPromote *FilterTest* +# # Tests should succeed with updated snapshots +> ++ 2.12 testOnly *FilterTest* +> ++ 2.13 testOnly *FilterTest* +> ++ 3 testOnly *FilterTest* +-> ++ 2.12 testOnly *OtherTest* +-> ++ 2.13 testOnly *OtherTest* +-> ++ 3 testOnly *OtherTest*