Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.3
// swift-tools-version:5.10

import PackageDescription

Expand All @@ -25,4 +25,4 @@ let package = Package(
path: "Tests/AllTests"
),
]
)
)
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![GitHub License](https://img.shields.io/github/license/XCEssentials/Requirement.svg?longCache=true)](LICENSE)
[![GitHub Tag](https://img.shields.io/github/tag/XCEssentials/Requirement.svg?longCache=true)](https://github.com/XCEssentials/Requirement/tags)
[![Swift Package Manager Compatible](https://img.shields.io/badge/SPM-compatible-brightgreen.svg?longCache=true)](Package.swift)
[![Written in Swift](https://img.shields.io/badge/Swift-5.3-orange.svg?longCache=true)](https://swift.org)
[![Written in Swift](https://img.shields.io/badge/Swift-5.10%2B-orange.svg?longCache=true)](https://swift.org)
[![Supported platforms](https://img.shields.io/badge/platforms-macOS%20%7C%20iOS%20%7C%20tvOS%20%7C%20watchOS%20%7C%20Linux-blue.svg?longCache=true)](Package.swift)
[![CI](https://github.com/XCEssentials/Requirement/actions/workflows/ci.yml/badge.svg)](https://github.com/XCEssentials/Requirement/actions/workflows/ci.yml)

Expand Down Expand Up @@ -35,7 +35,7 @@ Each requirement can be evaluated against a given data value (which can be an at

## How to install

The recommended way is to install using [SwiftPM](https://swift.org/package-manager/), but [Carthage](https://github.com/Carthage/Carthage) is also supported out of the box.
Install using [SwiftPM](https://swift.org/package-manager/). The package currently targets Swift tools version `5.10` and newer.

## How it works

Expand Down
175 changes: 147 additions & 28 deletions Tests/AllTests/AllTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,34 @@ class AllTests: XCTestCase
XCTFail("Unexpected failure")
}
}

func test_requirement_validate_rethrowsConditionEvaluationError()
{
enum TestError: Error { case brokenCondition }

let requirement = Requirement<Int>("Any value") { _ in
throw TestError.brokenCondition
}

XCTAssertThrowsError(try requirement.validate(14)) { error in
guard
case TestError.brokenCondition = error
else
{
return XCTFail("Unexpected error")
}
}
}


func test_requirement_unsatisfiedCondition()
{
let value = 0

do
{
XCTAssertThrowsError(
try Requirement("Non-zero value"){ $0 != value }.validate(value)
}
catch
{
)
{ error in
guard
let unsatisfiedRequirement = error as? UnsatisfiedRequirement
else
Expand All @@ -46,10 +62,61 @@ class AllTests: XCTestCase
}

XCTAssertEqual(unsatisfiedRequirement.description, "Non-zero value")
XCTAssert(unsatisfiedRequirement.input as! Int == value)
guard
let actualInput = unsatisfiedRequirement.input as? Int
else
{
return XCTFail("Unexpected input type")
}
XCTAssertEqual(actualInput, value)
XCTAssertTrue(unsatisfiedRequirement.context.function.contains("test_requirement_unsatisfiedCondition"))
}
}

func test_requirement_unsatisfiedCondition_customContext()
{
let requirement = Requirement<Int>("Non-zero value") { $0 != 0 }

XCTAssertThrowsError(
try requirement.validate(
file: "CustomFile.swift",
line: 42,
function: "customFunction()",
0
)
)
{ error in
guard
let unsatisfiedRequirement = error as? UnsatisfiedRequirement
else
{
return XCTFail("Unexpected validation error")
}

XCTAssertEqual(unsatisfiedRequirement.context.file, "CustomFile.swift")
XCTAssertEqual(unsatisfiedRequirement.context.line, 42)
XCTAssertEqual(unsatisfiedRequirement.context.function, "customFunction()")
}
}

func test_requirement_isValid()
{
let requirement = Requirement<Int>("Non-zero value") { $0 != 0 }

XCTAssertTrue(requirement.isValid(1))
XCTAssertFalse(requirement.isValid(0))
}

func test_requirement_isValid_returnsFalseOnThrownConditionError()
{
enum TestError: Error { case brokenCondition }

let requirement = Requirement<Int>("Any value") { _ in
throw TestError.brokenCondition
}

XCTAssertFalse(requirement.isValid(1))
}

func test_inlineCheck_success()
{
Expand Down Expand Up @@ -81,16 +148,13 @@ class AllTests: XCTestCase
}
}

do
{
XCTAssertThrowsError(
try Check.that("Non-zero value") {

try Container.failingProperty
}

}
catch
{
)
{ error in
guard
case let FailedCheck.errorDuringConditionCheck(desc, nestedError, context) = error
else
Expand All @@ -114,12 +178,10 @@ class AllTests: XCTestCase
{
let value = 0

do
{
XCTAssertThrowsError(
try Check.that("Non-zero value", value != 0 )
}
catch
{
)
{ error in
guard
case let FailedCheck.unsatisfiedCondition(desc, context) = error
else
Expand Down Expand Up @@ -180,12 +242,7 @@ class AllTests: XCTestCase
{
let value: Int? = nil

do
{
try Check.nonEmpty { value }
}
catch
{
XCTAssertThrowsError(try Check.nonEmpty { value }) { error in
switch error
{
case FailedCheck.unsatisfiedNonEmptyCondition(let desc, _):
Expand All @@ -196,12 +253,10 @@ class AllTests: XCTestCase
}
}

do
{
XCTAssertThrowsError(
try Check.nonEmpty("Custom check description") { value }
}
catch
{
)
{ error in
switch error
{
case FailedCheck.unsatisfiedNonEmptyCondition(let desc, _):
Expand All @@ -212,4 +267,68 @@ class AllTests: XCTestCase
}
}
}

func test_nonEmpty_errorDuringConditionCheck_whenInputThrows()
{
enum TestError: Error { case brokenCondition }

XCTAssertThrowsError(
try Check.nonEmpty("Value is set") { () -> Int? in
throw TestError.brokenCondition
}
)
{ error in
guard
case let FailedCheck.errorDuringConditionCheck(desc, nestedError, context) = error
else
{
return XCTFail("Unexpected validation error")
}

XCTAssertEqual(desc, "Value is set")
XCTAssertTrue(context.function.contains("test_nonEmpty_errorDuringConditionCheck_whenInputThrows"))
guard
case TestError.brokenCondition = nestedError
else
{
return XCTFail("Unexpected nested error")
}
}
}

func test_nonEmpty_unsatisfiedCondition_customContext()
{
let value: Int? = nil

XCTAssertThrowsError(
try Check.nonEmpty(
file: "CustomFile.swift",
line: 77,
function: "customFunction()",
"Value is set"
) { value }
)
{ error in
guard
case let FailedCheck.unsatisfiedNonEmptyCondition(desc, context) = error
else
{
return XCTFail("Unexpected validation error")
}

XCTAssertEqual(desc, "Value is set")
XCTAssertEqual(context.file, "CustomFile.swift")
XCTAssertEqual(context.line, 77)
XCTAssertEqual(context.function, "customFunction()")
}
}

func test_aliases_requireAndCondition()
{
let require: Require<Int> = Require("Non-zero value") { $0 != 0 }
let condition: Condition<Int> = Condition("Positive value") { $0 > 0 }

XCTAssertTrue(require.isValid(1))
XCTAssertFalse(condition.isValid(0))
}
}