minitest-markdown 0.2.1.pre → 0.2.2.pre
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +22 -18
- data/lib/minitest/markdown/configuration.rb +13 -10
- data/lib/minitest/markdown/{error.rb → errors.rb} +1 -3
- data/lib/minitest/markdown/test_class.rb +33 -7
- data/lib/minitest/markdown/test_code_block.rb +10 -8
- data/lib/minitest/markdown/version.rb +1 -1
- data/lib/minitest/markdown.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a9a40aad00d3cf796ff92234e9677cc452131a2ca0ff09936d77de0155e1cd7
|
4
|
+
data.tar.gz: 57e2ce0e6b9b4a3752a621dde91cdf8e483dca82efa4eb6373a2de04f2175769
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a09e92d607c2484518f8f23fac73e709de766b62f41d17bdfeaccc4931293b2e00cbdf35a5ad4872be6aae6f4022a6579d38dc31c23a5581191c16c85924b596
|
7
|
+
data.tar.gz: 96fbb9758bfd397dcce743c0f76c9e78e6155b4fd5f4a299e9c64bb304503732565f4310b348032a43fb4febccab3e7eb79b1cc12aa3a21b82563fc2760d829d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.2.2.pre] - 2025-05-08
|
4
|
+
|
5
|
+
- Improve magic comment & hook comment parsing
|
6
|
+
- Fix bug with empty sting after magic comment
|
7
|
+
- Fix bug in config if Bundler undefined
|
8
|
+
|
3
9
|
## [0.2.1.pre] - 2025-05-07
|
4
10
|
|
5
11
|
- Fix issue with require in eval
|
data/README.md
CHANGED
@@ -21,6 +21,17 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
21
21
|
gem install minitest-markdown
|
22
22
|
```
|
23
23
|
|
24
|
+
## Configuration
|
25
|
+
|
26
|
+
No configuation is required if you use Bundler. If not, set your `project_root` path using the setter method:
|
27
|
+
```ruby
|
28
|
+
@config = Markdown.config
|
29
|
+
# => instance_of Configuration
|
30
|
+
|
31
|
+
Configuration.instance_methods(false)
|
32
|
+
# => includes :project_root=
|
33
|
+
```
|
34
|
+
|
24
35
|
## Usage
|
25
36
|
|
26
37
|
### In your test class
|
@@ -106,13 +117,13 @@ Everything in the code blocks above runs as test code. [minitest-proveit](https:
|
|
106
117
|
It is possible to pass stubs to the generated tests. This is done using the stubs keyword. Hash keys represent the index of the test code block and the key is an instance of `StubChain`. `StubChain.stubproc` returns a procified stub which is called around the relevant test code. Zero or more of these reusable procs can be used to instantiate a StubChain object:
|
107
118
|
```ruby
|
108
119
|
class MarkdownTest < Minitest::Test
|
109
|
-
set_stubs_new = Minitest::StubChain.stubproc(Set, :new,
|
110
|
-
|
120
|
+
set_stubs_new = Minitest::StubChain.stubproc(Set, :new, Set.new) # returns a proc which stubs Set.new to return an empty set
|
121
|
+
set_stubs_size = Minitest::StubChain.stubproc(Set, :size, 42, any_instance: true) # uses the bundled minitest-stub_any_instance gem
|
111
122
|
|
112
123
|
stubs = {}
|
113
|
-
@stub_chain = Minitest::StubChain.new([set_stubs_new,
|
114
|
-
stubs[
|
115
|
-
stubs[
|
124
|
+
@stub_chain = Minitest::StubChain.new([set_stubs_new, set_stubs_size]) # initialized with zero or more stub procs
|
125
|
+
stubs[9] = @stub_chain
|
126
|
+
stubs[10] = @stub_chain # StubChain instances themseves may be reused
|
116
127
|
|
117
128
|
Markdown.generate_markdown_tests(self, stubs: stubs)
|
118
129
|
end
|
@@ -120,27 +131,20 @@ end
|
|
120
131
|
```
|
121
132
|
The 2 stubs above are demonstated in the following examples:
|
122
133
|
```ruby
|
123
|
-
# This is
|
124
|
-
Set.new([1, 'c', :s]).size # Here Set.new was stubbed to return an
|
134
|
+
# This is test_block9
|
135
|
+
Set.new([1, 'c', :s]).size # Here Set.new was stubbed to return an empty set and Set#size was stubbed to return 42
|
125
136
|
# => 42
|
126
137
|
```
|
127
138
|
Example showing the reuse of a StubChain:
|
128
139
|
```ruby
|
129
|
-
# This is
|
130
|
-
Set.new
|
140
|
+
# This is test_block10
|
141
|
+
Set.new.size
|
131
142
|
# => 42
|
132
143
|
```
|
133
144
|
|
134
|
-
|
145
|
+
### Errors
|
135
146
|
|
136
|
-
|
137
|
-
```ruby
|
138
|
-
@config = Markdown.config
|
139
|
-
# => instance_of Configuration
|
140
|
-
|
141
|
-
Configuration.instance_methods(false)
|
142
|
-
# => includes :project_root=
|
143
|
-
```
|
147
|
+
All errors subclass `Markdown::Error`
|
144
148
|
|
145
149
|
## Development
|
146
150
|
|
@@ -2,29 +2,32 @@
|
|
2
2
|
|
3
3
|
require 'pathname'
|
4
4
|
|
5
|
-
require_relative '
|
5
|
+
require_relative 'errors'
|
6
6
|
|
7
7
|
module Minitest
|
8
8
|
module Markdown
|
9
9
|
# configuration for gem
|
10
10
|
class Configuration
|
11
|
-
|
11
|
+
PROJECT_ROOT_UNDETERMINED = "Project root can't be determined, set with 'Markdown.config.project_root = /path'"
|
12
|
+
|
13
|
+
attr_writer :project_root
|
14
|
+
attr_accessor :prove_it
|
12
15
|
|
13
16
|
def initialize
|
14
|
-
@project_root = determine_project_root
|
17
|
+
@project_root = self.class.determine_project_root
|
15
18
|
@prove_it = true
|
16
19
|
end
|
17
20
|
|
18
|
-
def
|
19
|
-
|
21
|
+
def self.determine_project_root
|
22
|
+
Bundler.root if defined? Bundler
|
20
23
|
end
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
return Bundler.root if defined? Bundler
|
25
|
+
def project_root
|
26
|
+
@project_root || (raise Error, PROJECT_ROOT_UNDETERMINED)
|
27
|
+
end
|
26
28
|
|
27
|
-
|
29
|
+
def readme_path
|
30
|
+
project_root.join 'README.md'
|
28
31
|
end
|
29
32
|
end
|
30
33
|
end
|
@@ -13,12 +13,15 @@ module Minitest
|
|
13
13
|
HOOK_METHODS = %i[before_all after_all around around_all].freeze # minitest-hooks extension
|
14
14
|
NON_TEST_METHODS = %i[setup teardown].freeze
|
15
15
|
|
16
|
+
BAD_KLASS = 'TestClass must be instantiated with Minitest::Test or subclass thereof'
|
17
|
+
BAD_PATH = 'Path does not exist or is not readable:'
|
18
|
+
|
16
19
|
attr_reader :klass, :path
|
17
20
|
|
18
21
|
def initialize(klass, path: nil)
|
19
|
-
@klass = klass
|
22
|
+
@klass = validate_class(klass)
|
20
23
|
@config = Markdown.config
|
21
|
-
@path = path
|
24
|
+
@path = validate_path(path)
|
22
25
|
@ruby_blocks = parse_ruby_blocks
|
23
26
|
end
|
24
27
|
|
@@ -30,6 +33,19 @@ module Minitest
|
|
30
33
|
|
31
34
|
private
|
32
35
|
|
36
|
+
def validate_class(klass)
|
37
|
+
raise ArgumentError, BAD_KLASS unless klass.respond_to?(:ancestors) && klass.ancestors.include?(Minitest::Test)
|
38
|
+
|
39
|
+
klass
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate_path(path)
|
43
|
+
return @config.readme_path if path.nil?
|
44
|
+
raise ArgumentError, "#{BAD_PATH} #{path}" unless File.exist?(path) && File.file?(path)
|
45
|
+
|
46
|
+
path
|
47
|
+
end
|
48
|
+
|
33
49
|
def parse_ruby_blocks
|
34
50
|
File.new(path).read.scan(FENCED_BLOCK_REGEXP).flatten.map { |str| TestCodeBlock.new(str) }
|
35
51
|
end
|
@@ -54,13 +70,17 @@ module Minitest
|
|
54
70
|
end
|
55
71
|
|
56
72
|
def parse_non_test_method_block(type)
|
57
|
-
blocks = @ruby_blocks.map.select { |blk| blk
|
73
|
+
blocks = @ruby_blocks.map.select { |blk| parse_type(blk, type) }
|
58
74
|
return if blocks.empty?
|
59
|
-
raise Error
|
75
|
+
raise Error, "Multiple #{type} blocks are not allowed" if blocks.size > 1
|
60
76
|
|
61
77
|
@ruby_blocks.delete(blocks.first).fenced_block_str # hook method blocks can't be test methods
|
62
78
|
end
|
63
79
|
|
80
|
+
def parse_type(blk, type)
|
81
|
+
blk.fenced_block_str.lines.first.match?(/^\s*#\s*#{type}\s*\n$/)
|
82
|
+
end
|
83
|
+
|
64
84
|
def define_test_method(block, meth_index, stub_chain = nil)
|
65
85
|
stub_chain ||= StubChain.new
|
66
86
|
instance = self # scope
|
@@ -75,7 +95,7 @@ module Minitest
|
|
75
95
|
def evaluation_assertions(assertion_hash, bind)
|
76
96
|
ruby, assertion, args = TestCodeBlock::ASSERTION_KEYS.map { |key| assertion_hash[key] } # order dep
|
77
97
|
|
78
|
-
lmbda = -> {
|
98
|
+
lmbda = -> { kernel_eval(ruby) }
|
79
99
|
return unless assertion
|
80
100
|
return eval_with_block(bind, assertion, lmbda, args) if Assertions::WITH_BLOCK_EVAL.include? assertion
|
81
101
|
|
@@ -85,20 +105,26 @@ module Minitest
|
|
85
105
|
def eval_with_block(bind, assertion, actual, args)
|
86
106
|
return bind.receiver.send(assertion, &actual) if args.empty?
|
87
107
|
|
88
|
-
bind.receiver.send(assertion, *
|
108
|
+
bind.receiver.send(assertion, *kernel_eval(args), &actual)
|
89
109
|
end
|
90
110
|
|
91
111
|
def eval_without_block(bind, assertion, lmbda, args)
|
92
112
|
actual = lmbda.call
|
93
113
|
return bind.receiver.send(assertion, actual) if args == '[]'
|
94
114
|
|
95
|
-
expected, *rest =
|
115
|
+
expected, *rest = kernel_eval(args)
|
96
116
|
expected, actual = actual, expected if Assertions::EXPECTED_ACTUAL_REVERSED.include? assertion
|
97
117
|
kwargs = rest.last.is_a?(Hash) ? rest.last : nil
|
98
118
|
return bind.receiver.send(assertion, expected, actual, *rest) unless kwargs
|
99
119
|
|
100
120
|
bind.receiver.send(assertion, expected, actual, *rest, **kwargs) # assert_respond_to takes a kwarg..
|
101
121
|
end
|
122
|
+
|
123
|
+
def kernel_eval(args)
|
124
|
+
eval args # rubocop:disable Security/Eval
|
125
|
+
rescue SyntaxError
|
126
|
+
raise ArgumentError, "Invalid test code, failed to parse #{args}"
|
127
|
+
end
|
102
128
|
end
|
103
129
|
end
|
104
130
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'minifyrb' # DEP
|
4
4
|
|
5
5
|
require_relative '../assertions_extensions' # for assert_truthy
|
6
|
-
require_relative '../markdown/
|
6
|
+
require_relative '../markdown/errors'
|
7
7
|
|
8
8
|
module Minitest
|
9
9
|
module Markdown
|
@@ -16,9 +16,9 @@ module Minitest
|
|
16
16
|
|
17
17
|
ASSERTION_KEYS = %i[ruby assertion test_args].freeze
|
18
18
|
|
19
|
-
MAGIC_COMMENT_DELIMITER = '
|
20
|
-
MAGIC_COMMENT_REGEXP =
|
21
|
-
MAGIC_COMMENT_SCAN_REGEXP =
|
19
|
+
MAGIC_COMMENT_DELIMITER = '=>'
|
20
|
+
MAGIC_COMMENT_REGEXP = /^\s*#\s*#{MAGIC_COMMENT_DELIMITER}.*$/
|
21
|
+
MAGIC_COMMENT_SCAN_REGEXP = /^\s*#\s*#{MAGIC_COMMENT_DELIMITER}(.*)$/ # strips delimiter prefix
|
22
22
|
|
23
23
|
attr_reader :fenced_block_str
|
24
24
|
|
@@ -41,10 +41,12 @@ module Minitest
|
|
41
41
|
private
|
42
42
|
|
43
43
|
def assertions_arr
|
44
|
-
code_strings.zip(magic_comments.map { |s| parse(s) }).map(&:flatten)
|
44
|
+
code_strings.zip(magic_comments.each_with_index.map { |s, i| parse(s, i) }).map(&:flatten)
|
45
45
|
end
|
46
46
|
|
47
|
-
def parse(magic_comment_string)
|
47
|
+
def parse(magic_comment_string, idx)
|
48
|
+
raise ArgumentError, "Block#{idx} magic comment missing assertion or value" if magic_comment_string.strip.empty?
|
49
|
+
|
48
50
|
assertion = parse_assertion(magic_comment_string)
|
49
51
|
return [DEFAULT_ASSERTION, "[#{magic_comment_string}]"] if assertion.nil?
|
50
52
|
return [assertion, '[]'] if magic_comment_string.split.size == 1
|
@@ -57,14 +59,14 @@ module Minitest
|
|
57
59
|
end
|
58
60
|
|
59
61
|
def magic_comments
|
60
|
-
@fenced_block_str.scan(MAGIC_COMMENT_SCAN_REGEXP).flatten
|
62
|
+
@fenced_block_str.scan(MAGIC_COMMENT_SCAN_REGEXP).flatten.map(&:strip)
|
61
63
|
end
|
62
64
|
|
63
65
|
def code_strings
|
64
66
|
@fenced_block_str.split(MAGIC_COMMENT_REGEXP).map do |str|
|
65
67
|
Minifyrb::Minifier.new(str).minify.strip
|
66
68
|
rescue SyntaxError
|
67
|
-
raise Error
|
69
|
+
raise Error, "Syntax error in:\n\n#{str}"
|
68
70
|
end
|
69
71
|
end
|
70
72
|
end
|
data/lib/minitest/markdown.rb
CHANGED
@@ -4,7 +4,7 @@ require 'minitest/stub_any_instance'
|
|
4
4
|
|
5
5
|
require_relative 'stub_chain'
|
6
6
|
require_relative 'markdown/configuration'
|
7
|
-
require_relative 'markdown/
|
7
|
+
require_relative 'markdown/errors'
|
8
8
|
require_relative 'markdown/version'
|
9
9
|
require_relative 'markdown/test_class'
|
10
10
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minitest-markdown
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- MatzFan
|
@@ -77,7 +77,7 @@ files:
|
|
77
77
|
- lib/minitest/assertions_extensions.rb
|
78
78
|
- lib/minitest/markdown.rb
|
79
79
|
- lib/minitest/markdown/configuration.rb
|
80
|
-
- lib/minitest/markdown/
|
80
|
+
- lib/minitest/markdown/errors.rb
|
81
81
|
- lib/minitest/markdown/test_class.rb
|
82
82
|
- lib/minitest/markdown/test_code_block.rb
|
83
83
|
- lib/minitest/markdown/version.rb
|