From cb3504f032ba0d106b3273d30397ee4192b73ced Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 10 Sep 2026 16:31:22 +0000 Subject: [PATCH] Complete 7.1.0 changelog and move release docs to testbox-docs Audits the changelog against every commit since the 7.0.0 release (dc89555) and fills in the eleven user-facing changes that were missing, each tagged with its Jira ticket. Changelog: - Add the missing MockBox, reporter, date-equality, engine-detection, full-null and BoxLang CLI entries under [Unreleased] - Add a Changed section for the coverageEnabled default flip, which is a behavioral change - Correct the stale whats-new-with-7.0.0 filename reference The [Unreleased] section is left as-is. The release workflow stamps the version heading and compare links via keep-a-changelog-new-release. Removes the local docs/ folder. The 7.1.0 release page now lives in testbox-docs under readme/release-history/, alongside every prior release, and the changelog links to the published page instead. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_0126haQX77C4MLiK3fxwQ59A --- AGENTS.md | 1 - changelog.md | 36 ++- docs/whats-new-with-7.1.0.md | 489 ----------------------------------- 3 files changed, 25 insertions(+), 501 deletions(-) delete mode 100644 docs/whats-new-with-7.1.0.md diff --git a/AGENTS.md b/AGENTS.md index 9d3005c..617fbff 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -84,7 +84,6 @@ This repository ships domain skills in `.agents/skills`. Before implementing, re - `tests/specs/`: Main framework test specs. This directory contains both `.cfc` CFML specs and `.bx` BoxLang-only specs. - `bx/`: BoxLang browser/test harness assets. - `cfml/`: CFML browser/test harness assets. -- `docs/`: Release and feature documentation. - `test-visualizer/`: Static visualizer assets. ## Engine And File-Type Rules diff --git a/changelog.md b/changelog.md index 4a97b8b..16c6245 100644 --- a/changelog.md +++ b/changelog.md @@ -11,25 +11,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- BDD Class `skip` annotation support for skipping entire test classes. -- Add expectation context support via `expect( value ).withContext( message )` that prepends semantic context to all failure messages including negated matchers and custom matchers. -- Add collection expectation modes: `expectAny()`, `expectSome()`, and `expectNone()` alongside existing `expectAll()` with detailed failure summaries including element index/key and pass count reporting. -- Add grouped assertions via `$assert.all()`, `assertAll()` that run multiple assertion closures and report every failure at once instead of stopping at the first. -- Add new matchers: `toBeTruthy()`, `toBeFalsy()`, `toBeSameInstanceAs()`, `toHaveSize()`, `toThrowMatching()`, `toIncludeAll()`, `toIncludeAny()`, and `toIncludeNone()`. -- Add set expectations: `toBeASet()`, `toEqualSet()`, `toBeSubsetOf()`, `toBeSupersetOf()`, `toBeDisjointFrom()`, `toHaveUnion()`, `toHaveIntersection()`, `toHaveDifference()`, and `toHaveSymmetricDifference()` for working with BoxLang Set objects. -- Add range expectations: `toBeRange()`, `toContainValue()`, `toContainRange()`, `toBeInRange()`, `toBeBeforeRange()`, `toBeAfterRange()`, `toBeBounded()`, `toBeUnbounded()`, `toBeHalfBounded()`, `toBeIterable()`, `toBeAscending()`, `toBeDescending()`, `toHaveStep()`, and `toClampTo()` for BoxLang Range objects. -- Add data navigator expectations: `toHavePath()`, `toHavePathValue()`, `toHavePathType()`, `toHavePathSatisfying()`, `path()`, and `queryPath()` for navigating and asserting against nested BoxLang data structures using dot-notation, array indexes, wildcards, filters, and recursive descent. -- Add new assertion BIFs: `$assert.isTruthy()`, `$assert.isFalsy()`, `$assert.includesAll()`, `$assert.includesAny()`, and `$assert.includesNone()`. +- TESTBOX-451 BDD class `skip` annotation support for skipping entire test classes. +- TESTBOX-457 Expectation context support via `expect( value ).withContext( message )` that prepends semantic context to all failure messages including negated matchers and custom matchers. +- TESTBOX-458 Collection expectation modes: `expectAny()`, `expectSome()`, and `expectNone()` alongside existing `expectAll()` with detailed failure summaries including element index/key and pass count reporting. +- TESTBOX-459 Grouped assertions via `$assert.all()`, `assertAll()` that run multiple assertion closures and report every failure at once instead of stopping at the first. +- TESTBOX-460 New matchers: `toBeTruthy()`, `toBeFalsy()`, `toBeSameInstanceAs()`, `toHaveSize()`, `toThrowMatching()`, `toIncludeAll()`, `toIncludeAny()`, and `toIncludeNone()`. +- TESTBOX-461 Set expectations: `toBeASet()`, `toEqualSet()`, `toBeSubsetOf()`, `toBeSupersetOf()`, `toBeDisjointFrom()`, `toHaveUnion()`, `toHaveIntersection()`, `toHaveDifference()`, and `toHaveSymmetricDifference()` for working with BoxLang Set objects. +- TESTBOX-462 Range expectations: `toBeRange()`, `toContainValue()`, `toContainRange()`, `toBeInRange()`, `toBeBeforeRange()`, `toBeAfterRange()`, `toBeBounded()`, `toBeUnbounded()`, `toBeHalfBounded()`, `toBeIterable()`, `toBeAscending()`, `toBeDescending()`, `toHaveStep()`, and `toClampTo()` for BoxLang Range objects. +- TESTBOX-463 Data navigator expectations: `toHavePath()`, `toHavePathValue()`, `toHavePathType()`, `toHavePathSatisfying()`, `path()`, and `queryPath()` for navigating and asserting against nested BoxLang data structures using dot-notation, array indexes, wildcards, filters, and recursive descent. +- TESTBOX-464 New assertion BIFs: `$assert.isTruthy()`, `$assert.isFalsy()`, `$assert.includesAll()`, `$assert.includesAny()`, and `$assert.includesNone()`. + +### Changed + +- TESTBOX-466 The `coverageEnabled` URL parameter in the CFML test runner now defaults to `false` instead of `true`. Code coverage requires FusionReactor and is now opt-in. Pass `?coverageEnabled=true` to restore the previous behavior. ### Improvements +- TESTBOX-455 Expand the BoxLang CLI url-scope guard so it skips only when the scope truly isn't there, instead of assuming it is always absent in CLI mode. - Improve matcher failure messages with optional contextual prefix for distinguishing chained expectations. - Improve `expectAll()` failure messages to include pass/fail counts and per-element failure details with index/key context. -- Add `docs/whats-new-with-7.0.0.md` release page documenting all new assertion and expectation features. +- Add the [What's New With 7.1.0](https://testbox.ortusbooks.com/readme/release-history/whats-new-with-7.1.0) release page documenting all new assertion and expectation features. ### Fixed -- Fix custom matcher failure messages not routing through the expectation's internal fail method. +- TESTBOX-448 Fix MockBox `$args()` struct-order fragility and add Set/Range support to argument matching. +- TESTBOX-449 Encode HTML for bundle and spec names in the Simple reporter so markup in test names no longer breaks the report. +- TESTBOX-450 Equalize assertions now handle different types of date and date/time objects for equality, instead of blindly calling `actual.equals()`. +- TESTBOX-452 Fix `GetPageContextResponse()` error while running BoxLang in Adobe compatibility mode. +- TESTBOX-453 Fix the BoxLang CLI runner misreading its own script path as a positional bundle argument. +- TESTBOX-454 Fix `KeyNotFoundException [url]` crashing every CLI run on BoxLang 1.17+. +- TESTBOX-456 Simplify the BoxLang CLI url scope guard to a plain `param`. +- TESTBOX-465 Fix `isLucee()` returning `true` on BoxLang, which broke engine detection helpers and engine-conditional skips. +- TESTBOX-467 Support engines running with full null support enabled. +- TESTBOX-468 Fix custom matcher failure messages not routing through the expectation's internal fail method. ## [7.0.0] - 2026-03-17 diff --git a/docs/whats-new-with-7.1.0.md b/docs/whats-new-with-7.1.0.md deleted file mode 100644 index 8690cee..0000000 --- a/docs/whats-new-with-7.1.0.md +++ /dev/null @@ -1,489 +0,0 @@ -# What's New With TestBox 7.1.0 - -TestBox 7.1.0 introduces a significant upgrade to the assertions and expectations library, adding grouped assertions, collection expectation modes, rich failure diagnostics, and a suite of new matchers inspired by JUnit 5 and Jasmine. - -* * * - -## Expectation Context: `withContext()` - -Add semantic context to any expectation so failure messages include identifying information. Works with all matchers, negated matchers, and custom matchers. - -```javascript -it( "validates a user record", () => { - expect( user.age ) - .withContext( "user.age" ) - .toBeGT( 0 ) - - expect( user.email ) - .withContext( "user.email" ) - .toMatch( "@" ) -} ) -``` - -* * * - -## Collection Expectation Modes - -Three new collection modes complement the existing `expectAll()`. - -### `expectAny()` - -Passes when at least one element in the collection passes the chained matcher. - -```javascript -expectAny( products ).toSatisfy( p => p.onSale ) -``` - -### `expectSome()` - -Passes when a bounded number of elements pass. `max = 0` means no upper bound. - -```javascript -expectSome( users, min = 2, max = 5 ).toSatisfy( u => u.role == "admin" ) -expectSome( items, min = 3 ).toSatisfy( i => i.stock > 0 ) -``` - -### `expectNone()` - -Passes when zero elements pass the chained matcher. - -```javascript -expectNone( users ).toSatisfy( u => u.banned ) -``` - -### Improved `expectAll()` Failure Messages - -All collection modes now produce detailed failure summaries with pass/fail counts and per-element failure context including the element index or struct key. - -```javascript -try { - expectAll( [ 2, 4, 10, 8 ] ).toBeLT( 10 ) -} catch ( any e ) { - // e.message: "expectAll() failed: 1 of 4 element(s) did not pass the [toBeLT] expectation" - // e.detail: "Passed: 3 / 4\n\n[3]: The actual [10] is not less than [10]" -} -``` - -* * * - -## Grouped Assertions: `assertAll()` - -Run multiple assertion closures and report every failure at once — instead of stopping at the first. Non-assertion exceptions are rethrown immediately. - -```javascript -it( "validates a user record completely", () => { - assertAll( [ - () => expect( user.name ).notToBeEmpty(), - () => expect( user.email ).toMatch( "@" ), - () => expect( user.age ).toBeGTE( 18 ), - () => expect( user.age ).toBeLT( 120 ) - ] ) -} ) -``` - -Using the `$assert` style: - -```javascript -it( "xUnit style grouped assertions", () => { - $assert.all( - executables = [ - () => $assert.isTrue( true ), - () => $assert.isEqual( 1, 2 ), - () => $assert.notNull( javacast( "null", "" ) ) - ], - heading = "Basic checks" - ) -} ) -``` - -* * * - -## New Matchers - -### `toIncludeAll` / `toIncludeAny` / `toIncludeNone` - -Assert that a string or array contains all, any, or none of the given needles with case-insensitive matching. - -```javascript -expect( "hello world" ).toIncludeAll( [ "hello", "world" ] ) -expect( "hello world" ).toIncludeAny( [ "hello", "foo" ] ) -expect( "hello world" ).toIncludeNone( [ "foo", "bar" ] ) -``` - -### `toBeTruthy` / `toBeFalsy` - -Assert that a value is truthy (not false, `0`, empty string, or null) or falsy. - -```javascript -expect( 42 ).toBeTruthy() -expect( "" ).toBeFalsy() -``` - -### `toHaveSize` - -Alias for `toHaveLength()` — works on strings, arrays, structs, and queries. - -```javascript -expect( "abc" ).toHaveSize( 3 ) -expect( [ 1, 2 ] ).toHaveSize( 2 ) -expect( { a : 1, b : 2 } ).toHaveSize( 2 ) -``` - -### `toBeSameInstanceAs` - -Assert two references point to the exact same object instance. - -```javascript -var obj = { name : "test" } -expect( obj ).toBeSameInstanceAs( obj ) -``` - -### `toThrowMatching` - -Assert a function throws an exception that matches a predicate closure. - -```javascript -expect( () => { - throw( type = "FooException" ) -} ).toThrowMatching( e => e.type == "FooException" ) -``` - -* * * - -## New Assertion BIFs - -For xUnit-style testing, the following new `$assert` methods are available: - -| Method | Description | -| --- | --- | -| `$assert.isTruthy( actual, message )` | Value is truthy | -| `$assert.isFalsy( actual, message )` | Value is falsy | -| `$assert.includesAll( target, needles, message )` | Target contains every needle | -| `$assert.includesAny( target, needles, message )` | Target contains at least one needle | -| `$assert.includesNone( target, needles, message )` | Target contains no needle | -| `$assert.all( executables, heading )` | Run all assertions, report every failure | - -```javascript -$assert.isTruthy( "hello" ) -$assert.isFalsy( 0 ) -$assert.includesAll( "hello world", [ "hello", "world" ] ) -$assert.includesAny( [ "a", "b" ], [ "b", "z" ] ) -$assert.includesNone( "hello", [ "x", "y" ] ) -``` - -* * * - -## Set Expectations - -TestBox now provides a comprehensive suite of set-related matchers for working with BoxLang `Set` objects. These matchers leverage the global `setOf()` function to create sets and provide powerful assertions for set operations. - -### Creating Sets with `setOf()` - -```javascript -var set1 = setOf( 1, 2, 3 ) -var set2 = setOf( 3, 4, 5 ) -var set3 = setOf( 1, 2, 3, 4, 5 ) -var emptySet = setOf() -``` - -### `toBeASet()` / `notToBeASet()` - -Assert that a value is (or is not) a Set object. - -```javascript -expect( set1 ).toBeASet() -expect( [ 1, 2, 3 ] ).notToBeASet() -``` - -### `toEqualSet()` / `notToEqualSet()` - -Assert that two sets contain the same elements, regardless of order. - -```javascript -expect( setOf( 1, 2, 3 ) ).toEqualSet( setOf( 3, 2, 1 ) ) -expect( setOf( 'a', 'b' ) ).toEqualSet( setOf( 'b', 'a' ) ) -expect( setOf( 1, 'a', true ) ).toEqualSet( setOf( true, 'a', 1 ) ) -``` - -### `toBeSubsetOf()` / `notToBeSubsetOf()` - -Assert that all elements of the actual set are contained in the expected set. - -```javascript -expect( setOf( 1, 2 ) ).toBeSubsetOf( setOf( 1, 2, 3, 4, 5 ) ) -expect( setOf( 1, 2, 3, 4, 5 ) ).notToBeSubsetOf( setOf( 1, 2 ) ) -``` - -### `toBeSupersetOf()` / `notToBeSupersetOf()` - -Assert that the actual set contains all elements of the expected set. - -```javascript -expect( setOf( 1, 2, 3, 4, 5 ) ).toBeSupersetOf( setOf( 1, 2, 3 ) ) -expect( setOf( 1, 2, 3 ) ).notToBeSupersetOf( setOf( 1, 2, 3, 4, 5 ) ) -``` - -### `toBeDisjointFrom()` - -Assert that two sets share no common elements. - -```javascript -expect( setOf( 1, 2 ) ).toBeDisjointFrom( setOf( 3, 4 ) ) -``` - -### `toHaveUnion()` / `notToHaveUnion()` - -Assert that the union of two sets equals an expected set. - -```javascript -expect( setOf( 1, 2 ) ).toHaveUnion( setOf( 3, 4 ), setOf( 1, 2, 3, 4 ) ) -``` - -### `toHaveIntersection()` / `notToHaveIntersection()` - -Assert that the intersection of two sets equals an expected set. - -```javascript -expect( setOf( 1, 2, 3 ) ).toHaveIntersection( setOf( 3, 4, 5 ), setOf( 3 ) ) -``` - -### `toHaveDifference()` / `notToHaveDifference()` - -Assert that the set difference (actual - expected) equals an expected result. - -```javascript -expect( setOf( 1, 2, 3 ) ).toHaveDifference( setOf( 3, 4, 5 ), setOf( 1, 2 ) ) -``` - -### `toHaveSymmetricDifference()` / `notToHaveSymmetricDifference()` - -Assert that the symmetric difference (elements in either set but not both) equals an expected result. - -```javascript -expect( setOf( 1, 2, 3 ) ).toHaveSymmetricDifference( setOf( 3, 4, 5 ), setOf( 1, 2, 4, 5 ) ) -``` - -### Real-World Example: Menu Selection - -```javascript -it( "validates menu selection", () => { - var fruits = setOf( 'apple', 'banana', 'cherry' ) - var selected = setOf( 'apple', 'banana' ) - - expect( selected ).toBeSubsetOf( fruits ) - expect( selected ).toHaveIntersection( fruits, setOf( 'apple', 'banana' ) ) -} ) -``` - -* * * - -## Range Expectations (BoxLang) - -TestBox now includes a full set of matchers for BoxLang `Range` objects, including containment, ordering, bounds, and step/clamp assertions. - -> **BoxLang Only**: Range features depend on BoxLang range support. On CFML engines these expectations are guarded and report unsupported behavior cleanly. -> -> **Syntax Note**: BoxLang ranges are created with the `..` operator (for example `1..10`, `..10`, `1..`, `..`) and stepped via `.step( n )`. There is no `rangeNew()` BIF. - -### Core Range Matchers - -- `toBeRange()` -- `toContainValue( value )` -- `toContainRange( range )` -- `toBeInRange( range )` -- `toBeBeforeRange( range )` -- `toBeAfterRange( range )` - -### Range Shape And Direction - -- `toBeBounded()` -- `toBeUnbounded()` -- `toBeHalfBounded()` -- `toBeIterable()` -- `toBeAscending()` -- `toBeDescending()` - -### Step And Clamp - -- `toHaveStep( step )` -- `toClampTo( value, expected )` - -```javascript -var base = 1..10 -var stepped = (0..100).step( 5 ) -var chars = "a".."z" -var dates = createDate( 2024, 1, 1 )..createDate( 2024, 1, 31 ) - -expect( base ).toBeRange() -expect( base ).toContainValue( 5 ) -expect( base ).toContainRange( 3..7 ) -expect( 8 ).toBeInRange( base ) - -expect( stepped ).toHaveStep( 5 ) -expect( base ).toClampTo( 15, 10 ) -expect( dates ).toContainValue( "2024-01-15" ) - -expect( chars ).toBeAscending() -expect( chars ).toContainValue( "m" ) -``` - -Equivalent native Range API examples used under these matchers: - -```javascript -base.contains( 5 ) -base.contains( 3..7 ) -stepped.getStep() // 5 -base.clamp( 15 ) // 10 -``` - -* * * - -## Data Navigator Expectations - -TestBox now provides a suite of matchers that leverage BoxLang's built-in `dataNavigate()` BIF to safely navigate and assert against values in nested data structures. These matchers support dot-notation, array indexes, wildcards, filters, recursive descent, and all other JSONPath-style expressions. - -> **BoxLang Only**: Data navigator features require the BoxLang runtime and are guarded at the matcher level. On CFML engines they throw `TestBox.BoxLangFeatureNotAvailable`. - -### `toHavePath()` / `notToHavePath()` - -Assert that a path exists (or does not exist) in a nested data structure. - -```javascript -var data = { - "app" = { "name" = "TestApp", "settings" = { "debug" = true, "port" = 8080 } }, - "users" = [ { "name" = "Alice", "age" = 30 } ] -} - -expect( data ).toHavePath( "app.name" ) -expect( data ).toHavePath( "app.settings.debug" ) -expect( data ).toHavePath( "users[1].name" ) -expect( data ).notToHavePath( "nonexistent" ) -expect( data ).notToHavePath( "app.nonexistent" ) -``` - -### `toHavePathValue()` / `notToHavePathValue()` - -Assert that the value at a path matches an expected value. - -```javascript -expect( data ).toHavePathValue( "app.name", "TestApp" ) -expect( data ).toHavePathValue( "app.settings.port", 8080 ) -expect( data ).toHavePathValue( "app.settings.debug", true ) -expect( data ).toHavePathValue( "users[1].name", "Alice" ) -expect( data ).notToHavePathValue( "app.name", "WrongApp" ) -``` - -### `toHavePathType()` / `notToHavePathType()` - -Assert the type of the value at a path. Supports standard types (`string`, `numeric`, `boolean`, `struct`, `array`) and common aliases (`str`, `num`, `bool`, `arr`, `obj`, `map`). - -```javascript -expect( data ).toHavePathType( "app.name", "string" ) -expect( data ).toHavePathType( "app.settings.port", "numeric" ) -expect( data ).toHavePathType( "app.settings.debug", "boolean" ) -expect( data ).toHavePathType( "app.settings", "struct" ) -expect( data ).toHavePathType( "users", "array" ) -expect( data ).toHavePathType( "app.settings.port", "num" ) // alias -expect( data ).notToHavePathType( "app.name", "numeric" ) -``` - -### `toHavePathSatisfying()` / `notToHavePathSatisfying()` - -Assert that the value at a path satisfies a predicate closure. - -```javascript -expect( data ).toHavePathSatisfying( "app.name", name -> name == "TestApp" ) -expect( data ).toHavePathSatisfying( "app.settings.port", port -> port > 1000 ) -expect( data ).toHavePathSatisfying( "app.settings", settings -> settings.keyExists( "debug" ) ) -expect( data ).notToHavePathSatisfying( "app.name", name -> name == "WrongName" ) -``` - -### `path()` - -Navigate to a path and return a normal `Expectation` on the value at that path. Supports chaining any matcher on the result. - -```javascript -expect( data ).path( "app.name" ).toBe( "TestApp" ) -expect( data ).path( "app.settings.port" ).toBeGT( 8000 ) -expect( data ).path( "users" ).toHaveLength( 1 ) -expect( data ).path( "nonexistent" ).toBeNull() -``` - -### `queryPath()` - -Navigate to a path and return an `Expectation` on an array of all matching values. Fans out at wildcards, filters, and recursive descent segments. - -```javascript -expect( data ).queryPath( "users[*].name" ).toHaveLength( 1 ) -expect( data ).queryPath( "users[*].name" ).toInclude( "Alice" ) -expect( data ).queryPath( "nonexistent" ).toBeEmpty() -``` - -### Real-World Example: API Response Validation - -```javascript -it( "validates an API response", () => { - var response = { - "success" = true, - "data" = { - "users" = [ - { "name" = "Alice", "role" = "admin", "active" = true }, - { "name" = "Bob", "role" = "user", "active" = false } - ], - "metadata" = { "total" = 2, "page" = 1 } - } - } - - // Path existence - expect( response ).toHavePath( "data.users" ) - expect( response ).notToHavePath( "data.errors" ) - - // Path values - expect( response ).toHavePathValue( "success", true ) - expect( response ).toHavePathValue( "data.metadata.total", 2 ) - - // Path types - expect( response ).toHavePathType( "data.users", "array" ) - expect( response ).toHavePathType( "data.metadata.total", "numeric" ) - - // Predicate - expect( response ).toHavePathSatisfying( "data.users[1].role", role -> role == "admin" ) - - // Path extraction - expect( response ).path( "data.users[1].name" ).toBe( "Alice" ) - expect( response ).queryPath( "data.users[*].name" ).toInclude( "Bob" ) -} ) -``` - -## Summary - -| Feature | Type | Example | -| --- | --- | --- | -| `withContext()` | Expectation | `expect( v ).withContext( "label" ).toBe( x )` | -| `expectAny()` | Collection | `expectAny( arr ).toBeGT( 2 )` | -| `expectSome()` | Collection | `expectSome( arr, 2, 5 ).toBeGT( 2 )` | -| `expectNone()` | Collection | `expectNone( arr ).toBeEmpty()` | -| `assertAll()` | Grouped | `assertAll( closures, "heading" )` | -| `toBeTruthy()` | Matcher | `expect( v ).toBeTruthy()` | -| `toBeFalsy()` | Matcher | `expect( v ).toBeFalsy()` | -| `toBeSameInstanceAs()` | Matcher | `expect( a ).toBeSameInstanceAs( b )` | -| `toHaveSize()` | Matcher | `expect( v ).toHaveSize( 3 )` | -| `toThrowMatching()` | Matcher | `expect( fn ).toThrowMatching( p )` | -| `toIncludeAll()` | Matcher | `expect( v ).toIncludeAll( needles )` | -| `toIncludeAny()` | Matcher | `expect( v ).toIncludeAny( needles )` | -| `toIncludeNone()` | Matcher | `expect( v ).toIncludeNone( needles )` | -| `toBeASet()` / `nottoBeASet()` | Set | `expect( setOf( 1, 2 ) ).toBeASet()` | -| `toEqualSet()` / `notToEqualSet()` | Set | `expect( setOf( 1, 2 ) ).toEqualSet( setOf( 2, 1 ) )` | -| `toBeSubsetOf()` / `notToBeSubsetOf()` | Set | `expect( setOf( 1 ) ).toBeSubsetOf( setOf( 1, 2 ) )` | -| `toBeSupersetOf()` / `notToBeSupersetOf()` | Set | `expect( setOf( 1, 2 ) ).toBeSupersetOf( setOf( 1 ) )` | -| `toBeDisjointFrom()` | Set | `expect( setOf( 1 ) ).toBeDisjointFrom( setOf( 2 ) )` | -| `toHaveUnion()` / `notToHaveUnion()` | Set | `expect( setOf( 1 ) ).toHaveUnion( setOf( 2 ), setOf( 1, 2 ) )` | -| `toHaveIntersection()` / `notToHaveIntersection()` | Set | `expect( setOf( 1, 2 ) ).toHaveIntersection( setOf( 2, 3 ), setOf( 2 ) )` | -| `toHaveDifference()` / `notToHaveDifference()` | Set | `expect( setOf( 1, 2 ) ).toHaveDifference( setOf( 2 ), setOf( 1 ) )` | -| `toHaveSymmetricDifference()` / `notToHaveSymmetricDifference()` | Set | `expect( setOf( 1, 2 ) ).toHaveSymmetricDifference( setOf( 2, 3 ), setOf( 1, 3 ) )` | -| `toHavePath()` / `notToHavePath()` | Navigator | `expect( data ).toHavePath( "app.name" )` | -| `toHavePathValue()` / `notToHavePathValue()` | Navigator | `expect( data ).toHavePathValue( "app.name", "TestApp" )` | -| `toHavePathType()` / `notToHavePathType()` | Navigator | `expect( data ).toHavePathType( "app.settings.port", "numeric" )` | -| `toHavePathSatisfying()` / `notToHavePathSatisfying()` | Navigator | `expect( data ).toHavePathSatisfying( "app.name", p -> p == "TestApp" )` | -| `path()` | Navigator | `expect( data ).path( "app.name" ).toBe( "TestApp" )` | -| `queryPath()` | Navigator | `expect( data ).queryPath( "users[*].name" ).toInclude( "Alice" )` |