Merge remote-tracking branch 'origin/master' into mock-redesign
This commit is contained in:
commit
4148b80e58
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.12.0] - 2024-02-03
|
||||
### Added
|
||||
- Added ability to use matchers for case equality. [#55](https://github.com/icy-arctic-fox/spectator/issues/55)
|
||||
- Added support for nested case equality when checking arguments with Array, Tuple, Hash, and NamedTuple.
|
||||
|
||||
### Fixed
|
||||
- Fixed some issues with the `be_within` matcher when used with expected and union types.
|
||||
|
||||
## [0.11.7] - 2023-10-16
|
||||
### Fixed
|
||||
- Fix memoized value (`let`) with a union type causing segfault. [#81](https://gitlab.com/arctic-fox/spectator/-/issues/81)
|
||||
|
@ -450,7 +458,8 @@ This has been changed so that it compiles and raises an error at runtime with a
|
|||
First version ready for public use.
|
||||
|
||||
|
||||
[Unreleased]: https://gitlab.com/arctic-fox/spectator/-/compare/v0.11.7...master
|
||||
[Unreleased]: https://gitlab.com/arctic-fox/spectator/-/compare/v0.12.0...master
|
||||
[0.12.0]: https://gitlab.com/arctic-fox/spectator/-/compare/v0.11.7...v0.12.0
|
||||
[0.11.7]: https://gitlab.com/arctic-fox/spectator/-/compare/v0.11.6...v0.11.7
|
||||
[0.11.6]: https://gitlab.com/arctic-fox/spectator/-/compare/v0.11.5...v0.11.6
|
||||
[0.11.5]: https://gitlab.com/arctic-fox/spectator/-/compare/v0.11.4...v0.11.5
|
||||
|
|
|
@ -25,7 +25,7 @@ Add this to your application's `shard.yml`:
|
|||
development_dependencies:
|
||||
spectator:
|
||||
gitlab: arctic-fox/spectator
|
||||
version: ~> 0.11.0
|
||||
version: ~> 0.12.0
|
||||
```
|
||||
|
||||
Usage
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: spectator
|
||||
version: 0.11.7
|
||||
version: 0.12.0
|
||||
description: |
|
||||
Feature-rich testing framework for Crystal inspired by RSpec.
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
require "../spec_helper"
|
||||
|
||||
Spectator.describe "GitHub Issue #55" do
|
||||
GROUP_NAME = "CallCenter"
|
||||
|
||||
let(name) { "TimeTravel" }
|
||||
let(source) { "my.time.travel.experiment" }
|
||||
|
||||
class Analytics(T)
|
||||
property start_time = Time.local
|
||||
property end_time = Time.local
|
||||
|
||||
def initialize(@brain_talker : T)
|
||||
end
|
||||
|
||||
def instrument(*, name, source, &)
|
||||
@brain_talker.send(payload: {
|
||||
:group => GROUP_NAME,
|
||||
:name => name,
|
||||
:source => source,
|
||||
:start => start_time,
|
||||
:end => end_time,
|
||||
}, action: "analytics")
|
||||
end
|
||||
end
|
||||
|
||||
double(:brain_talker, send: nil)
|
||||
|
||||
let(brain_talker) { double(:brain_talker) }
|
||||
let(analytics) { Analytics.new(brain_talker) }
|
||||
|
||||
it "tracks the time it takes to run the block" do
|
||||
analytics.start_time = expected_start_time = Time.local
|
||||
expected_end_time = expected_start_time + 10.seconds
|
||||
analytics.end_time = expected_end_time + 0.5.seconds # Offset to ensure non-exact match.
|
||||
|
||||
analytics.instrument(name: name, source: source) do
|
||||
end
|
||||
|
||||
expect(brain_talker).to have_received(:send).with(payload: {
|
||||
:group => GROUP_NAME,
|
||||
:name => name,
|
||||
:source => source,
|
||||
:start => expected_start_time,
|
||||
:end => be_within(1.second).of(expected_end_time),
|
||||
}, action: "analytics")
|
||||
end
|
||||
end
|
|
@ -1,3 +1,4 @@
|
|||
require "../value"
|
||||
require "./match_data"
|
||||
|
||||
module Spectator::Matchers
|
||||
|
@ -22,6 +23,19 @@ module Spectator::Matchers
|
|||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
abstract def negated_match(actual : Expression(T)) : MatchData forall T
|
||||
|
||||
# Compares a matcher against a value.
|
||||
# Enables composable matchers.
|
||||
def ===(actual : Expression(T)) : Bool
|
||||
match(actual).matched?
|
||||
end
|
||||
|
||||
# Compares a matcher against a value.
|
||||
# Enables composable matchers.
|
||||
def ===(other) : Bool
|
||||
expression = Value.new(other)
|
||||
match(expression).matched?
|
||||
end
|
||||
|
||||
private def match_data_description(actual : Expression(T)) : String forall T
|
||||
match_data_description(actual.label)
|
||||
end
|
||||
|
|
|
@ -29,7 +29,26 @@ module Spectator::Matchers
|
|||
|
||||
# Checks whether the matcher is satisfied with the expression given to it.
|
||||
private def match?(actual : Expression(T)) : Bool forall T
|
||||
expected.value.includes?(actual.value)
|
||||
actual_value = actual.value
|
||||
expected_value = expected.value
|
||||
if expected_value.is_a?(Range) && actual_value.is_a?(Comparable)
|
||||
return match_impl?(expected_value, actual_value)
|
||||
end
|
||||
return false unless actual_value.is_a?(Comparable(typeof(expected_value.begin)))
|
||||
expected_value.includes?(actual_value)
|
||||
end
|
||||
|
||||
private def match_impl?(expected_value : Range(B, E), actual_value : Comparable(B)) : Bool forall B, E
|
||||
expected_value.includes?(actual_value)
|
||||
end
|
||||
|
||||
private def match_impl?(expected_value : Range(B, E), actual_value : T) : Bool forall B, E, T
|
||||
return false unless actual_value.is_a?(B) || actual_value.is_a?(Comparable(B))
|
||||
expected_value.includes?(actual_value)
|
||||
end
|
||||
|
||||
private def match_impl?(expected_value : Range(Number, Number), actual_value : Number) : Bool
|
||||
expected_value.includes?(actual_value)
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisfied.
|
||||
|
|
Loading…
Reference in New Issue