mirror of
https://github.com/jlengrand/atrium.git
synced 2026-03-10 08:01:19 +00:00
add Path.contains (#640)
This commit is contained in:
@@ -7,6 +7,7 @@ package ch.tutteli.atrium.api.fluent.en_GB
|
||||
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.logic.*
|
||||
import ch.tutteli.kbox.forElementAndForEachIn
|
||||
import java.nio.charset.Charset
|
||||
import java.nio.file.Path
|
||||
|
||||
@@ -310,6 +311,32 @@ fun <T : Path> Expect<T>.isAbsolute(): Expect<T> =
|
||||
fun <T : Path> Expect<T>.isRelative(): Expect<T> =
|
||||
_logicAppend { isRelative() }
|
||||
|
||||
/**
|
||||
* Expects that the subject of the assertion (a [Path]) is a directory;
|
||||
* meaning that there is a file system entry at the location the [Path] points to and that is a directory.
|
||||
*
|
||||
* Every argument string is expected to exist as a child file or child directory for the subject of the assertion.
|
||||
*
|
||||
* This assertion _resolves_ symbolic links.
|
||||
* Therefore, if a symbolic link exists at the location the subject points to, search will continue
|
||||
* at the location the link points at.
|
||||
*
|
||||
* This assertion is not atomic with respect to concurrent file system operations on the paths the assertions works on.
|
||||
* Its result, in particular its extended explanations, may be wrong if such concurrent file system operations
|
||||
* take place.
|
||||
*
|
||||
* @return An [Expect] for the current subject of the assertion.
|
||||
* @throws AssertionError Might throw an [AssertionError] if the assertion made is not correct.
|
||||
*
|
||||
* @since 0.14.0
|
||||
*/
|
||||
fun <T : Path> Expect<T>.contains(path: String, vararg otherPaths: String): Expect<T> =
|
||||
isDirectory() and {
|
||||
forElementAndForEachIn(path, otherPaths) { p ->
|
||||
resolve(p) { exists() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an [Expect] for the property [Path.extension][ch.tutteli.niok.extension]
|
||||
* (provided via [niok](https://github.com/robstoll/niok)) of the subject of the assertion,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module ch.tutteli.atrium.api.fluent.en_GB {
|
||||
requires ch.tutteli.atrium.logic;
|
||||
requires kotlin.stdlib;
|
||||
|
||||
requires ch.tutteli.kbox;
|
||||
|
||||
exports ch.tutteli.atrium.api.fluent.en_GB;
|
||||
exports ch.tutteli.atrium.api.fluent.en_GB.creating.charsequence.contains.builders;
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package ch.tutteli.atrium.api.fluent.en_GB
|
||||
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.specs.fun0
|
||||
import ch.tutteli.atrium.specs.fun1
|
||||
import ch.tutteli.atrium.specs.fun3
|
||||
import ch.tutteli.atrium.specs.notImplemented
|
||||
import ch.tutteli.atrium.specs.*
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
@@ -22,6 +19,7 @@ class PathAssertionsSpec : ch.tutteli.atrium.specs.integration.PathAssertionsSpe
|
||||
fun0(Expect<Path>::isDirectory),
|
||||
fun0(Expect<Path>::isAbsolute),
|
||||
fun0(Expect<Path>::isRelative),
|
||||
fun2<Path, String, Array<out String>>(Expect<Path>::contains),
|
||||
fun1(Expect<Path>::hasSameBinaryContentAs),
|
||||
fun3(Expect<Path>::hasSameTextualContentAs),
|
||||
fun1(Companion::hasSameTextualContentAsDefaultArgs)
|
||||
|
||||
@@ -5,6 +5,7 @@ import ch.tutteli.atrium.specs.fun1
|
||||
import ch.tutteli.atrium.specs.fun3
|
||||
import ch.tutteli.atrium.specs.notImplemented
|
||||
import ch.tutteli.atrium.specs.testutils.WithAsciiReporter
|
||||
import ch.tutteli.kbox.forElementAndForEachIn
|
||||
import java.nio.charset.Charset
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
@@ -23,6 +24,7 @@ class PathAssertionsSpec : ch.tutteli.atrium.specs.integration.PathAssertionsSpe
|
||||
"toBe ${aDirectory::class.simpleName}" to Companion::isDirectory,
|
||||
"toBe ${relative::class.simpleName}" to Companion::isAbsolute,
|
||||
"toBe ${relative::class.simpleName}" to Companion::isRelative,
|
||||
"contains not yet implemented in this API" to Companion::contains,
|
||||
fun1(Expect<Path>::hasSameBinaryContentAs),
|
||||
fun3(Companion::hasSameTextualContentAs),
|
||||
fun1(Companion::hasSameTextualContentAsDefaultArgs)
|
||||
@@ -38,6 +40,11 @@ class PathAssertionsSpec : ch.tutteli.atrium.specs.integration.PathAssertionsSpe
|
||||
private fun isDirectory(expect: Expect<Path>) = expect toBe aDirectory
|
||||
private fun isAbsolute(expect: Expect<Path>) = expect toBe absolute
|
||||
private fun isRelative(expect: Expect<Path>) = expect toBe relative
|
||||
private fun contains(expect: Expect<Path>, path: String, vararg otherPaths: String) = isDirectory(expect) and {
|
||||
forElementAndForEachIn(path, otherPaths) { p ->
|
||||
it resolve path(p) { it toBe existing }
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasSameTextualContentAs(
|
||||
expect: Expect<Path>,
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
|
||||
package ch.tutteli.atrium.api.fluent.en_GB.jdk8
|
||||
|
||||
import ch.tutteli.atrium.api.fluent.en_GB.contains
|
||||
import ch.tutteli.atrium.api.fluent.en_GB.isAbsolute
|
||||
import ch.tutteli.atrium.api.fluent.en_GB.isExecutable
|
||||
import ch.tutteli.atrium.api.fluent.en_GB.isRelative
|
||||
import ch.tutteli.atrium.creating.Expect
|
||||
import ch.tutteli.atrium.specs.fun0
|
||||
import ch.tutteli.atrium.specs.fun1
|
||||
import ch.tutteli.atrium.specs.fun3
|
||||
import ch.tutteli.atrium.specs.notImplemented
|
||||
import ch.tutteli.atrium.specs.*
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
@@ -28,6 +26,7 @@ class PathAssertionsSpec : ch.tutteli.atrium.specs.integration.PathAssertionsSpe
|
||||
fun0(Expect<Path>::isDirectory),
|
||||
fun0(Expect<Path>::isAbsolute), // checks the new function from fluent-jvm because it is not implemented in fluent-jkd8
|
||||
fun0(Expect<Path>::isRelative), // checks the new function from fluent-jvm because it is not implemented in fluent-jkd8
|
||||
fun2<Path, String, Array<out String>>(Expect<Path>::contains), // checks the new function from fluent-jvm because it is not implemented in fluent-jkd8
|
||||
fun1(Expect<Path>::hasSameBinaryContentAs),
|
||||
fun3(Expect<Path>::hasSameTextualContentAs),
|
||||
fun1(Companion::hasSameTextualContentAsDefaultArgs)
|
||||
|
||||
@@ -45,6 +45,7 @@ abstract class PathAssertionsSpec(
|
||||
isDirectory: Fun0<Path>,
|
||||
isAbsolute: Fun0<Path>,
|
||||
isRelative: Fun0<Path>,
|
||||
contains: Fun2<Path, String, Array<out String>>,
|
||||
hasSameBinaryContentAs: Fun1<Path, Path>,
|
||||
hasSameTextualContentAs: Fun3<Path, Path, Charset, Charset>,
|
||||
hasSameTextualContentAsDefaultArgs: Fun1<Path, Path>,
|
||||
@@ -66,6 +67,7 @@ abstract class PathAssertionsSpec(
|
||||
isDirectory.forSubjectLess(),
|
||||
isAbsolute.forSubjectLess(),
|
||||
isRelative.forSubjectLess(),
|
||||
contains.forSubjectLess("a", arrayOf("b", "c")),
|
||||
hasSameBinaryContentAs.forSubjectLess(Paths.get("a")),
|
||||
hasSameTextualContentAs.forSubjectLess(Paths.get("a"), Charsets.ISO_8859_1, Charsets.ISO_8859_1),
|
||||
hasSameTextualContentAsDefaultArgs.forSubjectLess(Paths.get("a"))
|
||||
@@ -868,6 +870,103 @@ abstract class PathAssertionsSpec(
|
||||
}
|
||||
}
|
||||
|
||||
describeFun(contains) {
|
||||
val containsFun = contains.lambda
|
||||
|
||||
listOf(
|
||||
ContainsTestData( "directory", "directories") { parent, name -> parent.newDirectory(name) },
|
||||
ContainsTestData("file", "files") { parent, name -> parent.newDirectory(name) }
|
||||
) .forEach {td ->
|
||||
it("does not throw if the single parameter is a child ${td.singleName}") withAndWithoutSymlink { maybeLink ->
|
||||
val folder = maybeLink.create(tempFolder.newDirectory("startDir"))
|
||||
maybeLink.create(td.factory.invoke(folder, "a"))
|
||||
expect(folder).containsFun("a", emptyArray())
|
||||
}
|
||||
|
||||
it("does not throw if both parameters are child ${td.multipleName}") withAndWithoutSymlink { maybeLink ->
|
||||
val folder = maybeLink.create(tempFolder.newDirectory("startDir"))
|
||||
maybeLink.create(td.factory.invoke(folder, "a"))
|
||||
maybeLink.create(td.factory.invoke(folder, "b"))
|
||||
expect(folder).containsFun("a", arrayOf("b"))
|
||||
}
|
||||
|
||||
it("does not throw if three parameters are child ${td.multipleName}") withAndWithoutSymlink { maybeLink ->
|
||||
val folder = maybeLink.create(tempFolder.newDirectory("startDir"))
|
||||
maybeLink.create(td.factory.invoke(folder, "a"))
|
||||
maybeLink.create(td.factory.invoke(folder, "b"))
|
||||
maybeLink.create(td.factory.invoke(folder, "c"))
|
||||
expect(folder).containsFun("a", arrayOf("b", "c"))
|
||||
}
|
||||
|
||||
it("it throws if the first ${td.singleName} does not exist") withAndWithoutSymlink { maybeLink ->
|
||||
val folder = maybeLink.create(tempFolder.newDirectory("startDir"))
|
||||
maybeLink.create(td.factory.invoke(folder, "file2"))
|
||||
maybeLink.create(td.factory.invoke(folder, "file3"))
|
||||
expect {
|
||||
expect(folder).containsFun("file1", arrayOf("file2", "file3"))
|
||||
}.toThrow<AssertionError>().message {
|
||||
contains("${TO.getDefault()}: ${EXIST.getDefault()}")
|
||||
contains("file1")
|
||||
containsNot("file2")
|
||||
containsNot("file3")
|
||||
}
|
||||
}
|
||||
|
||||
it("it throws if the second ${td.singleName} does not exist") withAndWithoutSymlink { maybeLink ->
|
||||
val folder = maybeLink.create(tempFolder.newDirectory("startDir"))
|
||||
maybeLink.create(td.factory.invoke(folder, "file1"))
|
||||
maybeLink.create(td.factory.invoke(folder, "file3"))
|
||||
expect {
|
||||
expect(folder).containsFun("file1", arrayOf("file2", "file3"))
|
||||
}.toThrow<AssertionError>().message {
|
||||
contains("${TO.getDefault()}: ${EXIST.getDefault()}")
|
||||
contains("file2")
|
||||
containsNot("file1")
|
||||
containsNot("file3")
|
||||
}
|
||||
}
|
||||
|
||||
it("it throws if third ${td.singleName} does not exist") withAndWithoutSymlink { maybeLink ->
|
||||
val folder = maybeLink.create(tempFolder.newDirectory("startDir"))
|
||||
maybeLink.create(td.factory.invoke(folder, "file1"))
|
||||
maybeLink.create(td.factory.invoke(folder, "file2"))
|
||||
expect {
|
||||
expect(folder).containsFun("file1", arrayOf("file2", "file3"))
|
||||
}.toThrow<AssertionError>().message {
|
||||
contains("${TO.getDefault()}: ${EXIST.getDefault()}")
|
||||
containsNot("file2")
|
||||
containsNot("file1")
|
||||
contains("file3")
|
||||
}
|
||||
}
|
||||
|
||||
it("it throws if the first and third ${td.singleName} do not exist") withAndWithoutSymlink { maybeLink ->
|
||||
val folder = maybeLink.create(tempFolder.newDirectory("startDir"))
|
||||
maybeLink.create(td.factory.invoke(folder, "file2"))
|
||||
expect {
|
||||
expect(folder).containsFun("file1", arrayOf("file2", "file3"))
|
||||
}.toThrow<AssertionError>().message {
|
||||
contains("${TO.getDefault()}: ${EXIST.getDefault()}")
|
||||
containsNot("file2")
|
||||
contains("file1")
|
||||
contains("file3")
|
||||
}
|
||||
}
|
||||
|
||||
it("it throws if the directory does not exist") withAndWithoutSymlink { maybeLink ->
|
||||
val folder = maybeLink.create(tempFolder.tmpDir.resolve("nonExistent"))
|
||||
val expectedMessage = "$isDescr: ${A_DIRECTORY.getDefault()}"
|
||||
|
||||
expect {
|
||||
expect(folder).containsFun("file1", arrayOf("file2", "file3"))
|
||||
}.toThrow<AssertionError>().message {
|
||||
contains(expectedMessage, FAILURE_DUE_TO_NO_SUCH_FILE.getDefault())
|
||||
containsExplanationFor(maybeLink)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describeFun(hasSameBinaryContentAs, hasSameTextualContentAs, hasSameTextualContentAsDefaultArgs) {
|
||||
val hasSameBinaryContentAsFun = hasSameBinaryContentAs.lambda
|
||||
val hasSameTextualContentAsFun = hasSameTextualContentAs.lambda
|
||||
@@ -1239,3 +1338,5 @@ private fun expectedPermissionTypeHintFor(type: Translatable, being: Translatabl
|
||||
type.getDefault(),
|
||||
being.getDefault()
|
||||
)
|
||||
|
||||
internal data class ContainsTestData(val singleName: String, val multipleName: String, val factory: (f: Path, name: String) -> Path)
|
||||
|
||||
Reference in New Issue
Block a user