minicrest 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +73 -0
  3. data/.yardopts +8 -0
  4. data/AGENTS.md +128 -0
  5. data/CHANGELOG.md +96 -0
  6. data/Gemfile +14 -0
  7. data/LICENSE +661 -0
  8. data/README.md +688 -0
  9. data/Rakefile +100 -0
  10. data/lib/minicrest/all_items.rb +61 -0
  11. data/lib/minicrest/anything.rb +58 -0
  12. data/lib/minicrest/asserter.rb +399 -0
  13. data/lib/minicrest/assertions.rb +411 -0
  14. data/lib/minicrest/between.rb +62 -0
  15. data/lib/minicrest/blank.rb +53 -0
  16. data/lib/minicrest/collection_item_matcher.rb +38 -0
  17. data/lib/minicrest/combinators.rb +340 -0
  18. data/lib/minicrest/comparison_matcher.rb +57 -0
  19. data/lib/minicrest/contains.rb +114 -0
  20. data/lib/minicrest/contains_exactly.rb +66 -0
  21. data/lib/minicrest/descends_from.rb +64 -0
  22. data/lib/minicrest/empty.rb +55 -0
  23. data/lib/minicrest/ends_with.rb +20 -0
  24. data/lib/minicrest/equals.rb +197 -0
  25. data/lib/minicrest/has_attribute.rb +96 -0
  26. data/lib/minicrest/has_key.rb +79 -0
  27. data/lib/minicrest/has_size.rb +88 -0
  28. data/lib/minicrest/has_value.rb +79 -0
  29. data/lib/minicrest/hash_entry_matchers.rb +119 -0
  30. data/lib/minicrest/includes.rb +114 -0
  31. data/lib/minicrest/is.rb +93 -0
  32. data/lib/minicrest/is_close_to.rb +61 -0
  33. data/lib/minicrest/is_greater_than.rb +30 -0
  34. data/lib/minicrest/is_greater_than_or_equal_to.rb +23 -0
  35. data/lib/minicrest/is_in.rb +84 -0
  36. data/lib/minicrest/is_less_than.rb +30 -0
  37. data/lib/minicrest/is_less_than_or_equal_to.rb +56 -0
  38. data/lib/minicrest/matcher.rb +91 -0
  39. data/lib/minicrest/matches_pattern.rb +60 -0
  40. data/lib/minicrest/no_items.rb +59 -0
  41. data/lib/minicrest/responds_to.rb +62 -0
  42. data/lib/minicrest/some_items.rb +59 -0
  43. data/lib/minicrest/starts_with.rb +20 -0
  44. data/lib/minicrest/string_matcher.rb +64 -0
  45. data/lib/minicrest/value_matchers.rb +86 -0
  46. data/lib/minicrest/version.rb +5 -0
  47. data/lib/minicrest.rb +110 -0
  48. data/minicrest.gemspec +35 -0
  49. metadata +108 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: efb95b1362535452ba9a0de78966811bde57ae5e89fb8c0e615613c756db1eca
4
+ data.tar.gz: 466d9c93d393382fe7d65135bcd38a05eb672c678995fb190b52fb0b452bf89c
5
+ SHA512:
6
+ metadata.gz: cacd32523d4bfef151600ee954e2838ddb6aa9c216c931e0e74cc907518e25b0b60e723f1526f4ef2b2465d0323aa68ef281f8bfe6253639056426207cc0b5e3
7
+ data.tar.gz: b8e7cf8b54371bc3965da8140bbae934897c0182d914c4294c1153a5e0cb15527f8754328f0224d6c76d7a9aa4b15b5f14caf4c6e02c8709a8453bbe5b089728
data/.rubocop.yml ADDED
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ plugins:
4
+ - rubocop-minitest
5
+
6
+ AllCops:
7
+ TargetRubyVersion: 3.4
8
+ NewCops: enable
9
+ SuggestExtensions: false
10
+
11
+ # Test files naturally have long describe/it blocks
12
+ Metrics/BlockLength:
13
+ Exclude:
14
+ - 'test/**/*'
15
+
16
+ # Gemspec required_ruby_version is intentionally broader than development version
17
+ Gemspec/RequiredRubyVersion:
18
+ Enabled: false
19
+
20
+ # Matcher factory methods intentionally use is_/has_ prefixes for readability
21
+ # e.g., descends_from(), has_size(), is_greater_than() - these are Hamcrest conventions
22
+ Naming/PredicatePrefix:
23
+ Exclude:
24
+ - 'lib/minicrest/assertions.rb'
25
+ - 'lib/minicrest/asserter.rb'
26
+ - 'lib/minicrest/has_attribute.rb'
27
+
28
+ # Diff methods are inherently complex but readable as-is
29
+ Metrics/AbcSize:
30
+ Exclude:
31
+ - 'lib/minicrest/equals.rb'
32
+ - 'lib/minicrest/asserter.rb'
33
+
34
+ Metrics/CyclomaticComplexity:
35
+ Exclude:
36
+ - 'lib/minicrest/equals.rb'
37
+ - 'lib/minicrest/includes.rb'
38
+ - 'lib/minicrest/asserter.rb'
39
+
40
+ Metrics/PerceivedComplexity:
41
+ Exclude:
42
+ - 'lib/minicrest/equals.rb'
43
+ - 'lib/minicrest/includes.rb'
44
+ - 'lib/minicrest/asserter.rb'
45
+
46
+ Metrics/MethodLength:
47
+ Exclude:
48
+ - 'lib/minicrest/equals.rb'
49
+ - 'lib/minicrest/includes.rb'
50
+ - 'lib/minicrest/asserter.rb'
51
+ - 'lib/minicrest/contains_exactly.rb'
52
+ - 'lib/minicrest/has_attribute.rb'
53
+
54
+ # Module documentation not required for simple matcher modules
55
+ Style/Documentation:
56
+ Exclude:
57
+ - 'lib/minicrest/equals.rb'
58
+ - 'lib/minicrest/is.rb'
59
+
60
+ # OpenStruct is fine for test fixtures
61
+ Style/OpenStructUse:
62
+ Exclude:
63
+ - 'test/**/*'
64
+
65
+ # Test helper classes defined in describe blocks are acceptable
66
+ Lint/ConstantDefinitionInBlock:
67
+ Exclude:
68
+ - 'test/**/*'
69
+
70
+ # Test matcher names with numbers are intentional for uniqueness
71
+ Naming/VariableNumber:
72
+ Exclude:
73
+ - 'test/**/*'
data/.yardopts ADDED
@@ -0,0 +1,8 @@
1
+ --title "Minicrest Documentation"
2
+ --main README.md
3
+ --markup markdown
4
+ lib/**/*.rb
5
+ -
6
+ README.md
7
+ CHANGELOG.md
8
+ LICENSE
data/AGENTS.md ADDED
@@ -0,0 +1,128 @@
1
+ # Building Guidelines for AI Assistants
2
+
3
+ This document provides guidelines for AI assistants (like Claude) when working on this project.
4
+
5
+ ## Development Philosophy
6
+
7
+ ### Test-Driven Development (TDD)
8
+
9
+ This project follows strict TDD:
10
+
11
+ 1. **Write a failing test first** (Red)
12
+ 2. **Write minimal code to pass the test** (Green)
13
+ 3. **Refactor while keeping tests green**
14
+ 4. **Commit after every green cycle**
15
+
16
+ **Never write production code without a failing test first.**
17
+
18
+ ### Grey-Box Testing Approach
19
+
20
+ - **Test observable behavior**, not implementation details
21
+ - **Favor integration tests** over isolated unit tests
22
+ - **Avoid mocking** except when absolutely necessary
23
+
24
+ ### Commit Strategy
25
+
26
+ - Commit after **every test goes green**
27
+ - Use **small, atomic commits**
28
+ - Commit message format:
29
+ - `change: <description>` - for changes to the observable behavior
30
+ - `refactor: <description>` - for refactors
31
+ - `chore: <description>` - for anything else: documentation, formatting, etc.
32
+
33
+ ## Project Structure
34
+
35
+ ```
36
+ gwt/
37
+ ├── .tool-versions # ASDF config file
38
+ ├── Gemfile # Bundler config file
39
+ ├── AGENTS.md # This file
40
+ ├── lib/ # Implementation of this library
41
+ ├── test/ # Test files
42
+ ```
43
+
44
+ ## TDD Workflow
45
+
46
+ ### 1. Before Writing Any Code
47
+
48
+ - Read the implementation plan (`docs/implementation-plan.md`)
49
+ - Identify the next TDD cycle to implement
50
+ - Understand the expected behavior
51
+
52
+ ### 2. Red Phase
53
+
54
+ Create a test file in `tests/` that mirrors the source structure:
55
+
56
+ - If implementing `lib/minicrest/foo.ts`, create `test/lib/minicrest/foo_test.rb`
57
+ - Write one or more tests that define the expected behavior
58
+ - Tests should **fail** when first run
59
+ - Run `minitest` to confirm failure
60
+
61
+ ### 3. Green Phase
62
+
63
+ - Create the corresponding source file in `lib/`
64
+ - Write **minimal code** to make the test pass
65
+ - Avoid over-engineering or adding features not tested
66
+ - Run `minitest` until all tests pass
67
+
68
+ ### 4. Commit
69
+
70
+ ```bash
71
+ git add tests/git/repo.test.ts src/git/repo.ts
72
+ git commit -m "Change: <describe the new behavior>"
73
+ ```
74
+
75
+ ### 5. Refactor Phase (optional)
76
+
77
+ - Wait until there's enough repetition to warrant refactoring. Skip this step if not applicable.
78
+ - Clean up code while keeping tests green
79
+ - Extract duplicated logic
80
+ - Improve naming
81
+ - Run `minitest` frequently to ensure tests still pass
82
+
83
+ ### 6. Commit
84
+
85
+ ```bash
86
+ git add tests/git/repo.test.ts src/git/repo.ts
87
+ git commit -m "Refactor: <describe the refactor>"
88
+ ```
89
+
90
+ ### 7. Repeat
91
+
92
+ Move to the next TDD cycle in the implementation plan.
93
+
94
+ ## Testing Guidelines
95
+
96
+ ### Test Observable Behavior
97
+
98
+ Focus on **what** the code does, not **how** it does it:
99
+ - Outputs
100
+ - Side effects
101
+ - Errors
102
+
103
+ ### Minimize Mocking
104
+
105
+ Use real implementations whenever possible:
106
+
107
+ ### Test Error Conditions
108
+
109
+ Test both success and failure paths:
110
+
111
+ ### Integration Tests
112
+
113
+ Test complete workflows
114
+
115
+ ## Summary: TDD Checklist
116
+
117
+ For each feature:
118
+
119
+ - [ ] Write failing test(s) that define expected behavior
120
+ - [ ] Run tests to confirm failure (`minitest`)
121
+ - [ ] Write minimal code to make tests pass
122
+ - [ ] Run tests to confirm success
123
+ - [ ] Commit the changes
124
+ - [ ] Refactor while keeping tests green
125
+ - [ ] Commit the refactor
126
+ - [ ] Move to next TDD cycle
127
+
128
+ **Remember**: Test first, code second, commit often!
data/CHANGELOG.md ADDED
@@ -0,0 +1,96 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2026-01-17
9
+
10
+ ### Added
11
+
12
+ - **Core matchers**
13
+ - `equals(expected)` - value equality with deep comparison
14
+ - `is(expected)` - reference equality (now supports matchers as well, e.g., `is(anything)`)
15
+ - `anything` - placeholder matcher that accepts any value
16
+ - `never(matcher)` - negation
17
+
18
+ - **Type and method matchers**
19
+ - `is_a(type)` (alias of `descends_from`) - type/class checking (including hierarchy)
20
+ - `descends_from(type)` - type/class checking (including hierarchy)
21
+ - `instance_of(type)` - exact class checking
22
+ - `responds_to(*methods)` - method presence checking
23
+
24
+ - **Value matchers**
25
+ - `nil_value` - matches `nil`
26
+ - `truthy` - matches any value that is not `nil` or `false`
27
+ - `falsy` - matches `nil` or `false`
28
+
29
+ - **String matchers**
30
+ - `starts_with(prefix)` - string prefix matching
31
+ - `ends_with(suffix)` - string suffix matching
32
+ - `matches_pattern(regex)` - regex pattern matching
33
+ - `blank` - blank string matching (empty or whitespace-only)
34
+
35
+ - **Size and emptiness matchers**
36
+ - `empty` - empty collection matching
37
+ - `has_size(expected)` - size/length matching (accepts matchers)
38
+
39
+ - **Numeric comparison matchers**
40
+ - `is_greater_than(n)`
41
+ - `is_greater_than_or_equal_to(n)`
42
+ - `is_less_than(n)`
43
+ - `is_less_than_or_equal_to(n)`
44
+ - `between(min, max, exclusive: false)` - range check
45
+ - `is_close_to(n, delta)` - floating-point tolerance
46
+
47
+ - **Collection content matchers**
48
+ - `includes(*items)` - partial containment (strings, arrays, hashes)
49
+ - `has_key(*keys)` - hash key presence
50
+ - `has_value(*values)` - hash value presence
51
+ - `contains(*items)` - exact items in any order
52
+ - `contains_exactly(*items)` - exact items in exact order
53
+
54
+ - **Collection item matchers**
55
+ - `all_items(matcher)` - all items must match
56
+ - `some_items(matcher)` - at least one item must match
57
+ - `no_items(matcher)` - no items should match
58
+ - `all_entries(matcher)` - all hash entries must match
59
+ - `some_entry(matcher)` - at least one hash entry must match
60
+ - `no_entry(matcher)` - no hash entries should match
61
+
62
+ - **Membership matcher**
63
+ - `is_in(collection)` - value membership in arrays, hashes, strings, ranges
64
+
65
+ - **Object attribute matcher**
66
+ - `has_attribute(name, matcher = nil)` - object/hash attribute checking
67
+
68
+ - **Error assertions**
69
+ - `raises_error(class = nil, message_matcher = nil)` - block raises error
70
+ - `raises_nothing` - block does not raise
71
+
72
+ - **Combinators**
73
+ - `&` operator - AND combination
74
+ - `|` operator - OR combination
75
+ - `all_of(*matchers)` - all matchers must match
76
+ - `some_of(*matchers)` - at least one matcher must match
77
+ - `none_of(*matchers)` - no matcher should match
78
+
79
+ - **Fluent API**
80
+ - `assert_that(actual).equals(expected)`
81
+ - `assert_that(actual).is(expected)`
82
+ - `assert_that(actual).never(matcher)` (aliases: `is_not`, `does_not`)
83
+ - `assert_that(actual).matches(matcher)`
84
+ - `assert_that { block }.raises_error`
85
+ - `assert_that { block }.raises_nothing`
86
+
87
+ - **Custom matcher API**
88
+ - `Minicrest.register_matcher(name, &block)` - register custom matchers
89
+ - Subclass `Minicrest::Matcher` to create custom matchers
90
+
91
+ - **Detailed failure messages**
92
+ - Hash diffs showing missing/extra/changed keys
93
+ - Array diffs showing index-based differences
94
+ - String diffs showing position of first difference
95
+
96
+ [1.0.0]: https://github.com/ggalmazor/minicrest/releases/tag/v1.0.0
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gem 'minitest'
6
+
7
+ group :development, :test do
8
+ gem 'rake', '~> 13.2'
9
+ gem 'rdoc', '~> 7.1'
10
+ gem 'rubocop', '~> 1.82'
11
+ gem 'rubocop-minitest', '~> 0.38.2'
12
+ gem 'webrick', '~> 1.9'
13
+ gem 'yard', '~> 0.9.38'
14
+ end