rundoc 2.0.1 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +10 -7
  3. data/CHANGELOG.md +15 -0
  4. data/CONTRIBUTING.md +25 -0
  5. data/README.md +35 -48
  6. data/Rakefile +5 -1
  7. data/bin/rundoc +4 -17
  8. data/lib/rundoc/cli.rb +208 -49
  9. data/lib/rundoc/cli_argument_parser.rb +140 -0
  10. data/lib/rundoc/code_command/bash.rb +8 -1
  11. data/lib/rundoc/code_command/rundoc/depend_on.rb +1 -24
  12. data/lib/rundoc/code_command/rundoc/require.rb +13 -7
  13. data/lib/rundoc/code_command/website/driver.rb +7 -5
  14. data/lib/rundoc/code_command/website/navigate.rb +1 -1
  15. data/lib/rundoc/code_command/website/screenshot.rb +7 -2
  16. data/lib/rundoc/code_command/website/visit.rb +4 -2
  17. data/lib/rundoc/code_section.rb +7 -7
  18. data/lib/rundoc/context/after_build.rb +14 -0
  19. data/lib/rundoc/context/execution.rb +22 -0
  20. data/lib/rundoc/parser.rb +8 -4
  21. data/lib/rundoc/version.rb +1 -1
  22. data/lib/rundoc.rb +13 -5
  23. data/rundoc.gemspec +1 -0
  24. data/test/fixtures/cnb/ruby/download.md +22 -0
  25. data/test/fixtures/cnb/ruby/image_structure.md +34 -0
  26. data/test/fixtures/cnb/ruby/intro.md +5 -0
  27. data/test/fixtures/cnb/ruby/multiple_langs.md +43 -0
  28. data/test/fixtures/cnb/ruby/rundoc.md +48 -0
  29. data/test/fixtures/cnb/ruby/what_is_pack_build.md +18 -0
  30. data/test/fixtures/cnb/shared/call_to_action.md +11 -0
  31. data/test/fixtures/cnb/shared/configure_builder.md +23 -0
  32. data/test/fixtures/cnb/shared/install_pack.md +14 -0
  33. data/test/fixtures/cnb/shared/pack_build.md +20 -0
  34. data/test/fixtures/cnb/shared/procfile.md +13 -0
  35. data/test/fixtures/cnb/shared/use_the_image.md +52 -0
  36. data/test/fixtures/cnb/shared/what_is_a_builder.md +18 -0
  37. data/test/fixtures/rails_4/rundoc.md +1 -1
  38. data/test/fixtures/rails_5/rundoc.md +1 -1
  39. data/test/fixtures/rails_7/rundoc.md +0 -1
  40. data/test/fixtures/rails_8/rundoc.md +481 -0
  41. data/test/fixtures/simple_git/rundoc.md +13 -0
  42. data/test/integration/after_build_test.rb +62 -0
  43. data/test/integration/print_test.rb +9 -9
  44. data/test/integration/require_test.rb +63 -0
  45. data/test/integration/website_test.rb +35 -0
  46. data/test/rundoc/cli_argument_parser_test.rb +118 -0
  47. data/test/rundoc/code_section_test.rb +40 -8
  48. data/test/rundoc/parser_test.rb +3 -3
  49. data/test/rundoc/peg_parser_test.rb +6 -6
  50. data/test/system/exe_cli_test.rb +231 -0
  51. data/test/test_helper.rb +74 -1
  52. metadata +41 -3
@@ -0,0 +1,62 @@
1
+ require "test_helper"
2
+
3
+ class IntegrationAfterBuildTest < Minitest::Test
4
+ def test_modifies_directory_structure
5
+ Dir.mktmpdir do |dir|
6
+ Dir.chdir(dir) do
7
+ dir = Pathname(dir)
8
+
9
+ source_path = dir.join("RUNDOC.md")
10
+ source_path.write <<~EOF
11
+ ```
12
+ :::>> $ mkdir lol
13
+ :::>> $ touch lol/rofl.txt
14
+ ```
15
+ EOF
16
+
17
+ io = StringIO.new
18
+
19
+ Rundoc::CLI.new(
20
+ io: io,
21
+ source_path: source_path,
22
+ on_success_dir: dir.join(SUCCESS_DIRNAME)
23
+ ).call
24
+
25
+ assert dir.join(SUCCESS_DIRNAME).join("lol").exist?
26
+ assert dir.join(SUCCESS_DIRNAME).join("lol").join("rofl.txt").exist?
27
+
28
+ FileUtils.remove_entry_secure(dir.join(SUCCESS_DIRNAME))
29
+
30
+ source_path.write <<~EOF
31
+ ```
32
+ :::-- rundoc.configure
33
+ Rundoc.configure do |config|
34
+ config.after_build do |context|
35
+ Dir.glob(context.output_dir.join("lol").join("*")).each do |item|
36
+ FileUtils.mv(item, context.output_dir)
37
+ end
38
+
39
+ FileUtils.rm_rf(context.output_dir.join("lol"))
40
+ end
41
+ end
42
+ ```
43
+
44
+ ```
45
+ :::>> $ mkdir lol
46
+ :::>> $ touch lol/rofl.txt
47
+ ```
48
+ EOF
49
+
50
+ io = StringIO.new
51
+
52
+ Rundoc::CLI.new(
53
+ io: io,
54
+ source_path: source_path,
55
+ on_success_dir: dir.join(SUCCESS_DIRNAME)
56
+ ).call
57
+
58
+ assert dir.join(SUCCESS_DIRNAME).join("rofl.txt").exist?
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,6 +1,6 @@
1
1
  require "test_helper"
2
2
 
3
- class ParserTest < Minitest::Test
3
+ class IntegrationPrintTest < Minitest::Test
4
4
  def test_erb_shared_binding_persists_values
5
5
  key = SecureRandom.hex
6
6
  contents = <<~RUBY
@@ -20,7 +20,7 @@ class ParserTest < Minitest::Test
20
20
  one
21
21
  #{key}
22
22
  EOF
23
- parsed = Rundoc::Parser.new(contents)
23
+ parsed = parse_contents(contents)
24
24
  actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
25
25
  assert_equal expected, actual
26
26
  end
@@ -43,7 +43,7 @@ class ParserTest < Minitest::Test
43
43
  expected = <<~EOF
44
44
  one
45
45
  EOF
46
- parsed = Rundoc::Parser.new(contents)
46
+ parsed = parse_contents(contents)
47
47
  actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
48
48
  assert_equal expected, actual
49
49
  end
@@ -69,7 +69,7 @@ class ParserTest < Minitest::Test
69
69
  there
70
70
  ```
71
71
  EOF
72
- parsed = Rundoc::Parser.new(contents)
72
+ parsed = parse_contents(contents)
73
73
  actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
74
74
  assert_equal expected, actual
75
75
  end
@@ -93,7 +93,7 @@ class ParserTest < Minitest::Test
93
93
  Hello
94
94
  there
95
95
  EOF
96
- parsed = Rundoc::Parser.new(contents)
96
+ parsed = parse_contents(contents)
97
97
  actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
98
98
  assert_equal expected, actual
99
99
  end
@@ -117,7 +117,7 @@ class ParserTest < Minitest::Test
117
117
  Hello
118
118
  there
119
119
  EOF
120
- parsed = Rundoc::Parser.new(contents)
120
+ parsed = parse_contents(contents)
121
121
  actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
122
122
  assert_equal expected, actual
123
123
  end
@@ -141,7 +141,7 @@ class ParserTest < Minitest::Test
141
141
  Hello
142
142
  there
143
143
  EOF
144
- parsed = Rundoc::Parser.new(contents)
144
+ parsed = parse_contents(contents)
145
145
  actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
146
146
  assert_equal expected, actual
147
147
  end
@@ -162,7 +162,7 @@ class ParserTest < Minitest::Test
162
162
  expected = <<~EOF
163
163
  Hello there
164
164
  EOF
165
- parsed = Rundoc::Parser.new(contents)
165
+ parsed = parse_contents(contents)
166
166
  actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
167
167
  assert_equal expected, actual
168
168
  end
@@ -185,7 +185,7 @@ class ParserTest < Minitest::Test
185
185
  Hello there
186
186
  ```
187
187
  EOF
188
- parsed = Rundoc::Parser.new(contents)
188
+ parsed = parse_contents(contents)
189
189
  actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
190
190
  assert_equal expected, actual
191
191
  end
@@ -0,0 +1,63 @@
1
+ require "test_helper"
2
+
3
+ class IntegrationRequireTest < Minitest::Test
4
+ def test_require_embeds_results
5
+ Dir.mktmpdir do |dir|
6
+ Dir.chdir(dir) do
7
+ dir = Pathname(dir)
8
+ source_path = dir.join("RUNDOC.md")
9
+ source_path.write <<~EOF
10
+ ```
11
+ :::>> rundoc.require "./day_one/rundoc.md"
12
+ ```
13
+ EOF
14
+
15
+ dir.join("day_one").tap(&:mkpath).join("rundoc.md").write <<~EOF
16
+ ```
17
+ :::-> print.text Hello World!
18
+ ```
19
+ EOF
20
+
21
+ parsed = parse_contents(
22
+ source_path.read,
23
+ source_path: source_path
24
+ )
25
+ actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
26
+ assert_equal "Hello World!", actual.strip
27
+ end
28
+ end
29
+ end
30
+
31
+ def test_require_runs_code_but_embeds_nothing_if_hidden
32
+ Dir.mktmpdir do |dir|
33
+ Dir.chdir(dir) do
34
+ dir = Pathname(dir)
35
+ source_path = dir.join("RUNDOC.md")
36
+ source_path.write <<~EOF
37
+ ```
38
+ :::-- rundoc.require "./day_one/rundoc.md"
39
+ ```
40
+ EOF
41
+
42
+ dir.join("day_one").tap(&:mkpath).join("rundoc.md").write <<~EOF
43
+ ```
44
+ :::-> print.text Hello World!
45
+ :::>> $ echo "echo hello world" > foo.txt
46
+ ```
47
+ EOF
48
+
49
+ parsed = parse_contents(
50
+ source_path.read,
51
+ source_path: source_path
52
+ )
53
+ actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
54
+ # Command was run
55
+ assert dir.join("foo.txt").exist?
56
+ assert "echo hello world", dir.join("foo.txt").read.strip
57
+
58
+ # But nothing was embedded
59
+ assert_equal "", actual.strip
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,35 @@
1
+ require "test_helper"
2
+
3
+ class IntegrationWebsiteTest < Minitest::Test
4
+ def test_screenshot_command
5
+ contents = <<~RUBY
6
+ ```
7
+ :::>> website.visit(name: "example", url: "http://example.com")
8
+ :::>> website.screenshot(name: "example")
9
+ ```
10
+ RUBY
11
+
12
+ Dir.mktmpdir do |dir|
13
+ Dir.chdir(dir) do
14
+ env = {}
15
+ env[:before] = []
16
+
17
+ screenshots_dirname = "screenshots"
18
+ screenshots_dir = Pathname(dir).join(screenshots_dirname)
19
+ screenshot_1_path = screenshots_dir.join("screenshot_1.png")
20
+
21
+ parsed = parse_contents(
22
+ contents,
23
+ output_dir: screenshots_dir.parent,
24
+ screenshots_dirname: screenshots_dirname
25
+ )
26
+ actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
27
+
28
+ expected = "![Screenshot of https://example.com/](screenshots/screenshot_1.png)"
29
+ assert_equal expected, actual.strip
30
+
31
+ assert screenshot_1_path.exist?
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,118 @@
1
+ require "test_helper"
2
+
3
+ class CliArgumentParserTest < Minitest::Test
4
+ def test_help
5
+ io = StringIO.new
6
+ exit_obj = FakeExit.new
7
+ parser = Rundoc::CLIArgumentParser.new(
8
+ io: io,
9
+ argv: ["--help"],
10
+ env: {},
11
+ exit_obj: exit_obj
12
+ )
13
+ parser.call
14
+ output = io.string
15
+
16
+ assert output.include?("Prints this help output")
17
+ end
18
+
19
+ def test_help_no_flag
20
+ io = StringIO.new
21
+ exit_obj = FakeExit.new
22
+ parser = Rundoc::CLIArgumentParser.new(
23
+ io: io,
24
+ argv: ["help"],
25
+ env: {},
26
+ exit_obj: exit_obj
27
+ )
28
+ parser.call
29
+ output = io.string
30
+
31
+ assert output.include?("Prints this help output")
32
+ end
33
+
34
+ def test_no_such_file
35
+ io = StringIO.new
36
+ exit_obj = FakeExit.new
37
+ parser = Rundoc::CLIArgumentParser.new(
38
+ io: io,
39
+ argv: ["fileDoesNotExist.txt"],
40
+ env: {},
41
+ exit_obj: exit_obj
42
+ )
43
+ parser.call
44
+ output = io.string
45
+
46
+ assert exit_obj.value == 1
47
+ assert_includes output, "No such file"
48
+ end
49
+
50
+ def test_dir_not_file
51
+ Dir.mktmpdir do |dir|
52
+ io = StringIO.new
53
+ exit_obj = FakeExit.new
54
+ parser = Rundoc::CLIArgumentParser.new(
55
+ io: io,
56
+ argv: [dir],
57
+ env: {},
58
+ exit_obj: exit_obj
59
+ )
60
+ parser.call
61
+ output = io.string
62
+
63
+ assert exit_obj.value == 1
64
+ assert_includes output, "Path is not a file"
65
+ end
66
+ end
67
+
68
+ def test_valid_inputs
69
+ Dir.mktmpdir do |dir|
70
+ Dir.chdir(dir) do
71
+ tmp = Pathname(dir)
72
+ rundoc = tmp.join("rundoc.md")
73
+ rundoc.write("")
74
+
75
+ io = StringIO.new
76
+ exit_obj = FakeExit.new
77
+ parser = Rundoc::CLIArgumentParser.new(
78
+ io: io,
79
+ argv: [
80
+ rundoc,
81
+ "--on-success-dir=./success",
82
+ "--on-failure-dir=./failure",
83
+ "--dotenv-path=./lol/.env",
84
+ "--screenshots-dirname=pics",
85
+ "--output-filename=OUTPUT.md",
86
+ "--force"
87
+ ],
88
+ env: {},
89
+ exit_obj: exit_obj
90
+ )
91
+ parser.call
92
+ output = io.string
93
+
94
+ assert !exit_obj.called?
95
+ assert output.empty?
96
+
97
+ assert_equal "./success", parser.options[:on_success_dir]
98
+ assert_equal "./failure", parser.options[:on_failure_dir]
99
+ assert_equal "./lol/.env", parser.options[:dotenv_path]
100
+ assert_equal "pics", parser.options[:screenshots_dirname]
101
+ assert_equal "OUTPUT.md", parser.options[:output_filename]
102
+ assert_equal true, parser.options[:force]
103
+
104
+ expected = [
105
+ :on_success_dir,
106
+ :on_failure_dir,
107
+ :dotenv_path,
108
+ :screenshots_dirname,
109
+ :output_filename,
110
+ :force,
111
+ :io,
112
+ :source_path
113
+ ]
114
+ assert_equal expected.sort, parser.options.keys.sort
115
+ end
116
+ end
117
+ end
118
+ end
@@ -15,7 +15,11 @@ class CodeSectionTest < Minitest::Test
15
15
  Dir.mktmpdir do |dir|
16
16
  Dir.chdir(dir) do
17
17
  match = contents.match(Rundoc::Parser::CODEBLOCK_REGEX)
18
- result = Rundoc::CodeSection.new(match, keyword: ":::").render
18
+ result = Rundoc::CodeSection.new(
19
+ match,
20
+ keyword: ":::",
21
+ context: default_context
22
+ ).render
19
23
  assert_equal "", result
20
24
  end
21
25
  end
@@ -30,7 +34,11 @@ class CodeSectionTest < Minitest::Test
30
34
  RUBY
31
35
 
32
36
  match = contents.match(Rundoc::Parser::CODEBLOCK_REGEX)
33
- result = Rundoc::CodeSection.new(match, keyword: ":::").render
37
+ result = Rundoc::CodeSection.new(
38
+ match,
39
+ keyword: ":::",
40
+ context: default_context
41
+ ).render
34
42
  assert_equal contents, result.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "\n")
35
43
  end
36
44
 
@@ -42,7 +50,11 @@ class CodeSectionTest < Minitest::Test
42
50
  RUBY
43
51
 
44
52
  match = contents.match(Rundoc::Parser::CODEBLOCK_REGEX)
45
- code_section = Rundoc::CodeSection.new(match, keyword: ":::")
53
+ code_section = Rundoc::CodeSection.new(
54
+ match,
55
+ keyword: ":::",
56
+ context: default_context
57
+ )
46
58
  code_section.render
47
59
 
48
60
  code_command = code_section.commands.first
@@ -56,7 +68,11 @@ class CodeSectionTest < Minitest::Test
56
68
  RUBY
57
69
 
58
70
  match = contents.match(Rundoc::Parser::CODEBLOCK_REGEX)
59
- code_section = Rundoc::CodeSection.new(match, keyword: ":::")
71
+ code_section = Rundoc::CodeSection.new(
72
+ match,
73
+ keyword: ":::",
74
+ context: default_context
75
+ )
60
76
  code_section.render
61
77
 
62
78
  code_command = code_section.commands.first
@@ -72,7 +88,11 @@ class CodeSectionTest < Minitest::Test
72
88
  RUBY
73
89
 
74
90
  match = contents.match(Rundoc::Parser::CODEBLOCK_REGEX)
75
- code_section = Rundoc::CodeSection.new(match, keyword: ":::")
91
+ code_section = Rundoc::CodeSection.new(
92
+ match,
93
+ keyword: ":::",
94
+ context: default_context
95
+ )
76
96
  code_section.render
77
97
 
78
98
  puts code_section.commands.inspect
@@ -89,7 +109,11 @@ class CodeSectionTest < Minitest::Test
89
109
  RUBY
90
110
 
91
111
  match = contents.match(Rundoc::Parser::CODEBLOCK_REGEX)
92
- code_section = Rundoc::CodeSection.new(match, keyword: ":::")
112
+ code_section = Rundoc::CodeSection.new(
113
+ match,
114
+ keyword: ":::",
115
+ context: default_context
116
+ )
93
117
  code_section.render
94
118
 
95
119
  code_command = code_section.commands.first
@@ -103,7 +127,11 @@ class CodeSectionTest < Minitest::Test
103
127
  RUBY
104
128
 
105
129
  match = contents.match(Rundoc::Parser::CODEBLOCK_REGEX)
106
- code_section = Rundoc::CodeSection.new(match, keyword: ":::")
130
+ code_section = Rundoc::CodeSection.new(
131
+ match,
132
+ keyword: ":::",
133
+ context: default_context
134
+ )
107
135
  code_section.render
108
136
 
109
137
  code_command = code_section.commands.first
@@ -119,7 +147,11 @@ class CodeSectionTest < Minitest::Test
119
147
  RUBY
120
148
 
121
149
  match = contents.match(Rundoc::Parser::CODEBLOCK_REGEX)
122
- code_section = Rundoc::CodeSection.new(match, keyword: ":::")
150
+ code_section = Rundoc::CodeSection.new(
151
+ match,
152
+ keyword: ":::",
153
+ context: default_context
154
+ )
123
155
  code_section.render
124
156
 
125
157
  code_command = code_section.commands.first
@@ -16,7 +16,7 @@ class ParserTest < Minitest::Test
16
16
  Dir.mktmpdir do |dir|
17
17
  Dir.chdir(dir) do
18
18
  expected = "sup\n\n```\n$ mkdir foo\n$ ls\nfoo\n```\n\nyo\n"
19
- parsed = Rundoc::Parser.new(contents)
19
+ parsed = parse_contents(contents)
20
20
  actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
21
21
  assert_equal expected, actual
22
22
  end
@@ -38,7 +38,7 @@ class ParserTest < Minitest::Test
38
38
  Dir.mktmpdir do |dir|
39
39
  Dir.chdir(dir) do
40
40
  expected = "sup\n\nIn file `foo/code.rb` write:\n\n```\na = 1 + 1\nb = a * 2\n```\nyo\n"
41
- parsed = Rundoc::Parser.new(contents)
41
+ parsed = parse_contents(contents)
42
42
  actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
43
43
  assert_equal expected, actual
44
44
  end
@@ -56,7 +56,7 @@ class ParserTest < Minitest::Test
56
56
  Dir.mktmpdir do |dir|
57
57
  Dir.chdir(dir) do
58
58
  expected = "\nIn file `foo/newb.rb` write:\n\n```\nputs 'hello world'\n$ cat foo/newb.rb\nputs 'hello world'\n```\n"
59
- parsed = Rundoc::Parser.new(contents)
59
+ parsed = parse_contents(contents)
60
60
  actual = parsed.to_md.gsub(Rundoc::CodeSection::AUTOGEN_WARNING, "")
61
61
  assert_equal expected, actual
62
62
  end
@@ -270,36 +270,36 @@ class PegParserTest < Minitest::Test
270
270
 
271
271
  def test_rundoc_sub_commands_no_quotes
272
272
  input = +""
273
- input << %(:::-- rundoc.depend_on ../foo/bar.md\n)
273
+ input << %(:::-- rundoc.require ../foo/bar.md\n)
274
274
 
275
275
  parser = Rundoc::PegParser.new.command_with_stdin
276
276
  tree = parser.parse_with_debug(input)
277
277
 
278
278
  actual = @transformer.apply(tree)
279
- assert_equal :"rundoc.depend_on", actual.keyword
279
+ assert_equal :"rundoc.require", actual.keyword
280
280
  end
281
281
 
282
282
  def test_seattle_style_method_call
283
283
  input = +""
284
- input << %(rundoc.depend_on '../foo/bar.md')
284
+ input << %(rundoc.require '../foo/bar.md')
285
285
  parser = Rundoc::PegParser.new.method_call
286
286
  tree = parser.parse_with_debug(input)
287
287
 
288
288
  actual = @transformer.apply(tree)
289
289
 
290
- assert_equal :"rundoc.depend_on", actual.keyword
290
+ assert_equal :"rundoc.require", actual.keyword
291
291
  end
292
292
 
293
293
  def test_rundoc_seattle_sub_command
294
294
  input = +""
295
- input << %(:::>> rundoc.depend_on '../foo/bar.md'\n)
295
+ input << %(:::>> rundoc.require '../foo/bar.md'\n)
296
296
 
297
297
  parser = Rundoc::PegParser.new.command
298
298
  tree = parser.parse_with_debug(input)
299
299
 
300
300
  actual = @transformer.apply(tree)
301
301
 
302
- assert_equal :"rundoc.depend_on", actual.keyword
302
+ assert_equal :"rundoc.require", actual.keyword
303
303
  end
304
304
 
305
305
  def test_positional_args