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.
- checksums.yaml +7 -0
- data/.rubocop.yml +73 -0
- data/.yardopts +8 -0
- data/AGENTS.md +128 -0
- data/CHANGELOG.md +96 -0
- data/Gemfile +14 -0
- data/LICENSE +661 -0
- data/README.md +688 -0
- data/Rakefile +100 -0
- data/lib/minicrest/all_items.rb +61 -0
- data/lib/minicrest/anything.rb +58 -0
- data/lib/minicrest/asserter.rb +399 -0
- data/lib/minicrest/assertions.rb +411 -0
- data/lib/minicrest/between.rb +62 -0
- data/lib/minicrest/blank.rb +53 -0
- data/lib/minicrest/collection_item_matcher.rb +38 -0
- data/lib/minicrest/combinators.rb +340 -0
- data/lib/minicrest/comparison_matcher.rb +57 -0
- data/lib/minicrest/contains.rb +114 -0
- data/lib/minicrest/contains_exactly.rb +66 -0
- data/lib/minicrest/descends_from.rb +64 -0
- data/lib/minicrest/empty.rb +55 -0
- data/lib/minicrest/ends_with.rb +20 -0
- data/lib/minicrest/equals.rb +197 -0
- data/lib/minicrest/has_attribute.rb +96 -0
- data/lib/minicrest/has_key.rb +79 -0
- data/lib/minicrest/has_size.rb +88 -0
- data/lib/minicrest/has_value.rb +79 -0
- data/lib/minicrest/hash_entry_matchers.rb +119 -0
- data/lib/minicrest/includes.rb +114 -0
- data/lib/minicrest/is.rb +93 -0
- data/lib/minicrest/is_close_to.rb +61 -0
- data/lib/minicrest/is_greater_than.rb +30 -0
- data/lib/minicrest/is_greater_than_or_equal_to.rb +23 -0
- data/lib/minicrest/is_in.rb +84 -0
- data/lib/minicrest/is_less_than.rb +30 -0
- data/lib/minicrest/is_less_than_or_equal_to.rb +56 -0
- data/lib/minicrest/matcher.rb +91 -0
- data/lib/minicrest/matches_pattern.rb +60 -0
- data/lib/minicrest/no_items.rb +59 -0
- data/lib/minicrest/responds_to.rb +62 -0
- data/lib/minicrest/some_items.rb +59 -0
- data/lib/minicrest/starts_with.rb +20 -0
- data/lib/minicrest/string_matcher.rb +64 -0
- data/lib/minicrest/value_matchers.rb +86 -0
- data/lib/minicrest/version.rb +5 -0
- data/lib/minicrest.rb +110 -0
- data/minicrest.gemspec +35 -0
- 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
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
|