mint 0.7.4 → 0.8.1

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 (70) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +23 -14
  3. data/LICENSE +22 -0
  4. data/README.md +68 -79
  5. data/bin/mint +47 -10
  6. data/bin/mint-epub +1 -4
  7. data/config/templates/base/style.css +187 -0
  8. data/config/templates/default/layout.erb +10 -0
  9. data/config/templates/default/style.css +237 -0
  10. data/config/templates/garden/layout.erb +38 -0
  11. data/config/templates/garden/style.css +303 -0
  12. data/config/templates/nord/layout.erb +11 -0
  13. data/config/templates/nord/style.css +339 -0
  14. data/config/templates/nord-dark/layout.erb +11 -0
  15. data/config/templates/nord-dark/style.css +339 -0
  16. data/config/templates/zen/layout.erb +11 -0
  17. data/config/templates/zen/style.css +114 -0
  18. data/lib/mint/command_line.rb +253 -111
  19. data/lib/mint/css.rb +11 -4
  20. data/lib/mint/css_parser.rb +76 -0
  21. data/lib/mint/css_template.rb +37 -0
  22. data/lib/mint/document.rb +203 -43
  23. data/lib/mint/helpers.rb +50 -10
  24. data/lib/mint/layout.rb +2 -3
  25. data/lib/mint/markdown_template.rb +47 -0
  26. data/lib/mint/mint.rb +181 -114
  27. data/lib/mint/plugin.rb +3 -3
  28. data/lib/mint/plugins/epub.rb +1 -2
  29. data/lib/mint/resource.rb +19 -9
  30. data/lib/mint/style.rb +10 -14
  31. data/lib/mint/version.rb +1 -1
  32. data/lib/mint.rb +1 -0
  33. data/man/mint.1 +135 -0
  34. data/spec/cli/README.md +99 -0
  35. data/spec/cli/argument_parsing_spec.rb +237 -0
  36. data/spec/cli/bin_integration_spec.rb +348 -0
  37. data/spec/cli/configuration_management_spec.rb +363 -0
  38. data/spec/cli/full_workflow_integration_spec.rb +527 -0
  39. data/spec/cli/publish_workflow_spec.rb +368 -0
  40. data/spec/cli/template_management_spec.rb +300 -0
  41. data/spec/css_parser_spec.rb +149 -0
  42. data/spec/css_spec.rb +1 -1
  43. data/spec/document_spec.rb +102 -69
  44. data/spec/helpers_spec.rb +42 -42
  45. data/spec/mint_spec.rb +104 -80
  46. data/spec/plugin_spec.rb +141 -143
  47. data/spec/run_cli_tests.rb +95 -0
  48. data/spec/spec_helper.rb +8 -1
  49. data/spec/style_spec.rb +18 -16
  50. data/spec/support/cli_helpers.rb +169 -0
  51. data/spec/support/fixtures/content-2.md +16 -0
  52. data/spec/support/matchers.rb +1 -1
  53. metadata +116 -224
  54. data/config/syntax.yaml +0 -71
  55. data/config/templates/base/style.sass +0 -144
  56. data/config/templates/default/css/style.css +0 -158
  57. data/config/templates/default/layout.haml +0 -8
  58. data/config/templates/default/style.sass +0 -36
  59. data/config/templates/protocol/layout.haml +0 -7
  60. data/config/templates/protocol/style.sass +0 -20
  61. data/config/templates/zen/css/style.css +0 -145
  62. data/config/templates/zen/layout.haml +0 -7
  63. data/config/templates/zen/style.sass +0 -24
  64. data/features/config.feature +0 -21
  65. data/features/plugins/epub.feature +0 -23
  66. data/features/publish.feature +0 -73
  67. data/features/support/env.rb +0 -15
  68. data/features/templates.feature +0 -79
  69. data/spec/command_line_spec.rb +0 -87
  70. data/spec/plugins/epub_spec.rb +0 -242
@@ -0,0 +1,99 @@
1
+ # Mint CLI Test Suite
2
+
3
+ This directory contains a comprehensive test suite for the Mint command-line interface.
4
+
5
+ ## Test structure
6
+
7
+ ### Core test files
8
+
9
+ - **`argument_parsing_spec.rb`** – Tests command-line argument parsing and option handling
10
+ - **`template_management_spec.rb`** – Tests template installation, uninstallation, editing, and listing
11
+ - **`publish_workflow_spec.rb`** – Tests markdown publishing, file discovery, and output generation
12
+ - **`configuration_management_spec.rb`** – Tests configuration setting, reading, and scope management
13
+ - **`bin_integration_spec.rb`** – Tests actual `bin/mint` executable integration
14
+ - **`full_workflow_integration_spec.rb`** – End-to-end workflow tests for common user scenarios
15
+
16
+ ### Support files
17
+
18
+ - **`../support/cli_helpers.rb`** – Helper methods for CLI testing (temp directories, file creation, output capture)
19
+ - **`run_cli_tests.rb`** – Custom test runner with better output formatting
20
+
21
+ ## Running tests
22
+
23
+ ### Run all CLI tests
24
+
25
+ ```bash
26
+ # Using custom runner (recommended)
27
+ spec/run_cli_tests.rb
28
+
29
+ # Using RSpec directly
30
+ rspec spec/cli/ --format documentation
31
+ ```
32
+
33
+ ### Run specific test suites
34
+
35
+ ```bash
36
+ # Individual test suites
37
+ spec/run_cli_tests.rb argument_parsing
38
+ spec/run_cli_tests.rb template_management
39
+ spec/run_cli_tests.rb publish_workflow
40
+
41
+ # Or with RSpec
42
+ rspec spec/cli/argument_parsing_spec.rb
43
+ ```
44
+
45
+ ### Run integration tests only
46
+
47
+ ```bash
48
+ rspec spec/cli/full_workflow_integration_spec.rb
49
+ ```
50
+
51
+ ## Helper methods
52
+
53
+ The `cli_helpers.rb` provides utilities for:
54
+
55
+ ```ruby
56
+ # Temporary directories
57
+ in_temp_dir do |dir|
58
+ # Test code runs in isolated temp directory
59
+ end
60
+
61
+ # Output capture
62
+ stdout, stderr = capture_output do
63
+ Mint::CommandLine.some_method
64
+ end
65
+
66
+ # File creation
67
+ create_markdown_file("test.md", "# Content")
68
+ create_template_directory("custom", with_layout: true)
69
+
70
+ # Command execution
71
+ result = run_command("mint", "publish", "file.md")
72
+
73
+ # Content verification
74
+ verify_file_content("output.html") do |content|
75
+ expect(content).to include("expected text")
76
+ end
77
+ ```
78
+
79
+ ## Debugging failed tests
80
+
81
+ ### Common issues
82
+ 1. **Missing templates** – Tests create minimal templates; check `create_template_directory`
83
+ 2. **File paths** – All paths should be relative within temp directory
84
+ 3. **Configuration** – Use `setup_basic_config` to establish minimal config
85
+
86
+ ### Debug helpers
87
+
88
+ ```ruby
89
+ # Print current directory contents
90
+ puts Dir.glob("**/*")
91
+
92
+ # Print file contents
93
+ puts File.read("problematic.html") rescue "FILE NOT FOUND"
94
+
95
+ # Print configuration
96
+ puts YAML.load_file(".mint/config.yaml") rescue "NO CONFIG"
97
+ ```
98
+
99
+ This test suite provides comprehensive coverage of Mint's CLI functionality while being maintainable and fast to run.
@@ -0,0 +1,237 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "CLI Argument Parsing" do
4
+ describe "Mint::CommandLine.parse" do
5
+ context "with no arguments" do
6
+ it "returns default options and empty argv" do
7
+ result = Mint::CommandLine.parse([])
8
+
9
+ expect(result[:argv]).to eq([])
10
+ expect(result[:options][:root]).to eq(Dir.getwd)
11
+ expect(result[:options][:scope]).to eq(:local)
12
+ expect(result[:options][:layout_or_style_or_template]).to eq([:template, 'default'])
13
+ expect(result[:help]).to include("Usage: mint")
14
+ end
15
+ end
16
+
17
+ context "with template options" do
18
+ it "parses --template option" do
19
+ result = Mint::CommandLine.parse(["--template", "zen", "file.md"])
20
+
21
+ expect(result[:argv]).to eq(["file.md"])
22
+ expect(result[:options][:layout_or_style_or_template]).to eq([:template, "zen"])
23
+ end
24
+
25
+ it "parses --layout option" do
26
+ result = Mint::CommandLine.parse(["--layout", "custom", "file.md"])
27
+
28
+ expect(result[:argv]).to eq(["file.md"])
29
+ expect(result[:options][:layout_or_style_or_template]).to eq([:layout, "custom"])
30
+ end
31
+
32
+ it "parses -l option for layout" do
33
+ result = Mint::CommandLine.parse(["-l", "custom", "file.md"])
34
+
35
+ expect(result[:argv]).to eq(["file.md"])
36
+ expect(result[:options][:layout_or_style_or_template]).to eq([:layout, "custom"])
37
+ end
38
+
39
+ it "parses --style option" do
40
+ result = Mint::CommandLine.parse(["--style", "minimal", "file.md"])
41
+
42
+ expect(result[:argv]).to eq(["file.md"])
43
+ expect(result[:options][:layout_or_style_or_template]).to eq([:style, "minimal"])
44
+ end
45
+
46
+ it "handles short flags for templates" do
47
+ result = Mint::CommandLine.parse(["-t", "pro", "file.md"])
48
+ expect(result[:options][:layout_or_style_or_template]).to eq([:template, "pro"])
49
+
50
+ result = Mint::CommandLine.parse(["--layout", "custom", "file.md"])
51
+ expect(result[:options][:layout_or_style_or_template]).to eq([:layout, "custom"])
52
+
53
+ result = Mint::CommandLine.parse(["-s", "clean", "file.md"])
54
+ expect(result[:options][:layout_or_style_or_template]).to eq([:style, "clean"])
55
+ end
56
+ end
57
+
58
+ context "with path options" do
59
+ it "parses --root option" do
60
+ result = Mint::CommandLine.parse(["--root", "/custom/path", "file.md"])
61
+
62
+ expect(result[:options][:root]).to eq("/custom/path")
63
+ end
64
+
65
+ it "parses --destination option" do
66
+ result = Mint::CommandLine.parse(["--destination", "output", "file.md"])
67
+
68
+ expect(result[:options][:destination]).to eq("output")
69
+ end
70
+
71
+ it "parses --style-destination option" do
72
+ result = Mint::CommandLine.parse(["--style-destination", "css", "file.md"])
73
+
74
+ expect(result[:options][:style_destination]).to eq("css")
75
+ end
76
+ end
77
+
78
+ context "with output options" do
79
+ it "parses --output-file option" do
80
+ result = Mint::CommandLine.parse(["--output-file", "custom.html", "file.md"])
81
+
82
+ expect(result[:options][:output_file]).to eq("custom.html")
83
+ end
84
+
85
+ it "has default output file format" do
86
+ result = Mint::CommandLine.parse(["file.md"])
87
+
88
+ expect(result[:options][:output_file]).to eq('#{basename}.#{new_extension}')
89
+ end
90
+ end
91
+
92
+ context "with scope options" do
93
+ it "parses --global scope" do
94
+ result = Mint::CommandLine.parse(["--global", "file.md"])
95
+
96
+ expect(result[:options][:scope]).to eq(:global)
97
+ end
98
+
99
+ it "parses --user scope" do
100
+ result = Mint::CommandLine.parse(["--user", "file.md"])
101
+
102
+ expect(result[:options][:scope]).to eq(:user)
103
+ end
104
+
105
+ it "parses --local scope (default)" do
106
+ result = Mint::CommandLine.parse(["--local", "file.md"])
107
+
108
+ expect(result[:options][:scope]).to eq(:local)
109
+ end
110
+
111
+ it "handles short scope flags" do
112
+ result = Mint::CommandLine.parse(["-g"])
113
+ expect(result[:options][:scope]).to eq(:global)
114
+
115
+ result = Mint::CommandLine.parse(["-u"])
116
+ expect(result[:options][:scope]).to eq(:user)
117
+ end
118
+ end
119
+
120
+ context "with boolean flags" do
121
+ it "parses --recursive flag" do
122
+ result = Mint::CommandLine.parse(["--recursive"])
123
+
124
+ expect(result[:options][:recursive]).to be true
125
+ end
126
+
127
+ it "handles short recursive flag" do
128
+ result = Mint::CommandLine.parse(["-r"])
129
+
130
+ expect(result[:options][:recursive]).to be true
131
+ end
132
+
133
+ it "defaults recursive to false" do
134
+ result = Mint::CommandLine.parse([])
135
+
136
+ expect(result[:options][:recursive]).to be false
137
+ end
138
+ end
139
+
140
+ context "with mixed arguments" do
141
+ it "parses complex argument combinations" do
142
+ args = [
143
+ "--template", "zen",
144
+ "--root", "/custom",
145
+ "--destination", "out",
146
+ "--recursive",
147
+ "--global",
148
+ "file1.md", "file2.md"
149
+ ]
150
+
151
+ result = Mint::CommandLine.parse(args)
152
+
153
+ expect(result[:argv]).to eq(["file1.md", "file2.md"])
154
+ expect(result[:options][:layout_or_style_or_template]).to eq([:template, "zen"])
155
+ expect(result[:options][:root]).to eq("/custom")
156
+ expect(result[:options][:destination]).to eq("out")
157
+ expect(result[:options][:recursive]).to be true
158
+ expect(result[:options][:scope]).to eq(:global)
159
+ end
160
+ end
161
+
162
+ context "argument processing utilities" do
163
+ describe ".process_output_format" do
164
+ it "processes basename substitution" do
165
+ result = Mint::CommandLine.process_output_format(
166
+ '#{basename}.html',
167
+ 'document.md'
168
+ )
169
+
170
+ expect(result).to eq('document.html')
171
+ end
172
+
173
+ it "processes original_extension substitution" do
174
+ result = Mint::CommandLine.process_output_format(
175
+ '#{basename}.#{original_extension}.bak',
176
+ 'document.md'
177
+ )
178
+
179
+ expect(result).to eq('document.md.bak')
180
+ end
181
+
182
+ it "processes new_extension substitution" do
183
+ result = Mint::CommandLine.process_output_format(
184
+ '#{basename}.#{new_extension}',
185
+ 'document.md'
186
+ )
187
+
188
+ expect(result).to eq('document.html')
189
+ end
190
+
191
+ it "processes complex format strings" do
192
+ result = Mint::CommandLine.process_output_format(
193
+ 'output/#{basename}-converted.#{new_extension}',
194
+ 'docs/readme.md'
195
+ )
196
+
197
+ expect(result).to eq('output/readme-converted.html')
198
+ end
199
+
200
+ it "handles files without extensions" do
201
+ result = Mint::CommandLine.process_output_format(
202
+ '#{basename}.#{new_extension}',
203
+ 'README'
204
+ )
205
+
206
+ expect(result).to eq('README.html')
207
+ end
208
+ end
209
+ end
210
+
211
+ context "with style mode options" do
212
+ it "parses --style-mode inline" do
213
+ result = Mint::CommandLine.parse(["--style-mode", "inline", "file.md"])
214
+
215
+ expect(result[:options][:style_mode]).to eq(:inline)
216
+ end
217
+
218
+ it "parses --style-mode external" do
219
+ result = Mint::CommandLine.parse(["--style-mode", "external", "file.md"])
220
+
221
+ expect(result[:options][:style_mode]).to eq(:external)
222
+ end
223
+
224
+ it "parses --style-mode original" do
225
+ result = Mint::CommandLine.parse(["--style-mode", "original", "file.md"])
226
+
227
+ expect(result[:options][:style_mode]).to eq(:original)
228
+ end
229
+
230
+ it "defaults to inline style mode" do
231
+ result = Mint::CommandLine.parse(["file.md"])
232
+
233
+ expect(result[:options][:style_mode]).to eq(:inline)
234
+ end
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,348 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Bin Script Integration" do
4
+ describe "mint executable" do
5
+ let(:mint_bin) { File.expand_path("../../../bin/mint", __FILE__) }
6
+ let(:project_root) { File.expand_path("../../..", __FILE__) }
7
+
8
+ context "in isolated environment" do
9
+ around(:each) do |example|
10
+ in_temp_dir do |dir|
11
+ @test_dir = dir
12
+ # Copy bin scripts to test directory for isolation
13
+ FileUtils.cp_r("#{project_root}/bin", ".")
14
+ FileUtils.cp_r("#{project_root}/lib", ".")
15
+
16
+ # Make sure bin script is executable
17
+ FileUtils.chmod(0755, "bin/mint")
18
+ example.run
19
+ end
20
+ end
21
+
22
+ describe "basic command functionality" do
23
+ it "shows help when run with no arguments" do
24
+ result = run_command("ruby", "bin/mint")
25
+
26
+ expect(result.success?).to be true
27
+ expect(result.stdout).to include("Usage:")
28
+ end
29
+
30
+ it "shows help with --help flag" do
31
+ result = run_command("ruby", "bin/mint", "--help")
32
+
33
+ expect(result.stdout).to include("Usage: mint [command] files [options]")
34
+ expect(result.stdout).to include("--template")
35
+ expect(result.stdout).to include("--layout")
36
+ expect(result.stdout).to include("--style")
37
+ end
38
+
39
+ it "shows version information" do
40
+ # Assuming there's a --version flag or similar
41
+ # This might need adjustment based on actual implementation
42
+ result = run_command("ruby", "bin/mint", "--version")
43
+
44
+ # This test might fail if --version isn't implemented
45
+ # In that case, we could test a different way to get version info
46
+ end
47
+ end
48
+
49
+ describe "publish command" do
50
+ it "publishes markdown files via CLI" do
51
+ create_markdown_file("test.md", "# Hello from CLI")
52
+ setup_basic_config
53
+ create_template_directory("default")
54
+
55
+ result = run_command({"MINT_NO_PIPE" => "1"}, "ruby", "bin/mint", "publish", "test.md")
56
+
57
+ expect(result.success?).to be true
58
+ expect(File.exist?("test.html")).to be true
59
+
60
+ content = File.read("test.html")
61
+ expect(content).to include("Hello from CLI")
62
+ end
63
+
64
+ it "handles multiple files" do
65
+ create_markdown_file("doc1.md", "# Document 1")
66
+ create_markdown_file("doc2.md", "# Document 2")
67
+ setup_basic_config
68
+ create_template_directory("default")
69
+
70
+ result = run_command({"MINT_NO_PIPE" => "1"}, "ruby", "bin/mint", "publish", "doc1.md", "doc2.md")
71
+
72
+ expect(result.success?).to be true
73
+ expect(File.exist?("doc1.html")).to be true
74
+ expect(File.exist?("doc2.html")).to be true
75
+ end
76
+
77
+ it "respects template options" do
78
+ create_markdown_file("styled.md", "# Styled Document")
79
+ setup_basic_config
80
+ create_template_directory("default")
81
+ create_template_directory("custom")
82
+
83
+ # Write a distinctive custom template
84
+ File.write(".mint/templates/custom/layout.erb",
85
+ "<html><body class='custom-style'><%= content %></body></html>")
86
+ File.write(".mint/templates/custom/style.css",
87
+ "body { background: red; }")
88
+
89
+ result = run_command({"MINT_NO_PIPE" => "1"}, "ruby", "bin/mint", "publish", "--template", "custom", "styled.md")
90
+
91
+ expect(result.success?).to be true
92
+ expect(File.exist?("styled.html")).to be true
93
+
94
+ content = File.read("styled.html")
95
+ expect(content).to include("custom-style")
96
+ end
97
+
98
+ it "handles recursive publishing" do
99
+ FileUtils.mkdir_p("docs/sub")
100
+ create_markdown_file("docs/index.md", "# Index")
101
+ create_markdown_file("docs/sub/page.md", "# Sub Page")
102
+ setup_basic_config
103
+ create_template_directory("default")
104
+
105
+ result = run_command({"MINT_NO_PIPE" => "1"}, "ruby", "bin/mint", "publish", "--recursive", "docs")
106
+
107
+ expect(result.success?).to be true
108
+ expect(File.exist?("docs/index.html")).to be true
109
+ expect(File.exist?("docs/sub/page.html")).to be true
110
+ end
111
+
112
+ it "handles errors gracefully" do
113
+ result = run_command({"MINT_NO_PIPE" => "1"}, "ruby", "bin/mint", "publish", "nonexistent.md")
114
+
115
+ expect(result.success?).to be false
116
+ expect(result.stderr + result.stdout).to match(/error|Error|No such file|ENOENT/i)
117
+ end
118
+ end
119
+
120
+ describe "template management commands" do
121
+ it "lists templates" do
122
+ setup_basic_config
123
+ create_template_directory("custom1")
124
+ create_template_directory("custom2")
125
+
126
+ result = run_command("ruby", "bin/mint", "templates")
127
+
128
+ expect(result.success?).to be true
129
+ expect(result.stdout).to include("custom1")
130
+ expect(result.stdout).to include("custom2")
131
+ end
132
+
133
+ it "installs templates" do
134
+ create_template_file("my-layout.erb", :layout, "<html><%= yield %></html>")
135
+
136
+ result = run_command("ruby", "bin/mint", "install", "my-layout.erb", "mynew")
137
+
138
+ expect(result.success?).to be true
139
+ expect(File.exist?(".mint/templates/mynew/layout.erb")).to be true
140
+ end
141
+
142
+ it "uninstalls templates" do
143
+ setup_basic_config
144
+ create_template_directory("removeme")
145
+
146
+ # Verify it exists first
147
+ expect(File.exist?(".mint/templates/removeme")).to be true
148
+
149
+ result = run_command("ruby", "bin/mint", "uninstall", "removeme")
150
+
151
+ expect(result.success?).to be true
152
+ expect(File.exist?(".mint/templates/removeme")).to be false
153
+ end
154
+
155
+ it "edits templates" do
156
+ setup_basic_config
157
+ create_template_directory("editable", with_layout: true)
158
+
159
+ # Mock the editor to avoid opening a real editor
160
+ result = run_command(
161
+ {"EDITOR" => "echo 'edited'"},
162
+ "ruby", "bin/mint", "edit-layout", "editable"
163
+ )
164
+
165
+ expect(result.success?).to be true
166
+ end
167
+ end
168
+
169
+ describe "configuration commands" do
170
+ it "displays current configuration" do
171
+ setup_basic_config
172
+
173
+ result = run_command("ruby", "bin/mint", "config")
174
+
175
+ expect(result.success?).to be true
176
+ expect(result.stdout).to include("layout")
177
+ expect(result.stdout).to include("default")
178
+ end
179
+
180
+ it "sets configuration values" do
181
+ result = run_command("ruby", "bin/mint", "set", "layout", "custom-layout")
182
+
183
+ expect(result.success?).to be true
184
+ expect(File.exist?(".mint/config.yaml")).to be true
185
+
186
+ config = YAML.load_file(".mint/config.yaml")
187
+ expect(config["layout"]).to eq("custom-layout")
188
+ end
189
+
190
+ it "handles scope flags for configuration" do
191
+ result = run_command("ruby", "bin/mint", "set", "--local", "style", "local-style")
192
+
193
+ expect(result.success?).to be true
194
+
195
+ config = YAML.load_file(".mint/config.yaml")
196
+ expect(config["style"]).to eq("local-style")
197
+ end
198
+ end
199
+
200
+ describe "plugin commands" do
201
+ it "handles epub plugin" do
202
+ create_markdown_file("book.md", "# My Book\n\nContent here.")
203
+
204
+ # This might fail if epub dependencies aren't available
205
+ result = run_command("ruby", "bin/mint-epub", "publish", "book.md")
206
+
207
+ # We expect this to either work or fail gracefully
208
+ # The specific behavior depends on whether epub dependencies are installed
209
+ expect([true, false]).to include(result.success?)
210
+ end
211
+ end
212
+
213
+ describe "error handling and edge cases" do
214
+ it "handles unknown commands gracefully" do
215
+ result = run_command("ruby", "bin/mint", "unknown-command")
216
+
217
+ expect(result.success?).to be false
218
+ expect(result.stderr + result.stdout).to match(/error|Usage/)
219
+ end
220
+
221
+ it "handles malformed arguments" do
222
+ result = run_command("ruby", "bin/mint", "publish", "--invalid-flag")
223
+
224
+ expect(result.success?).to be false
225
+ end
226
+
227
+ it "provides helpful error messages" do
228
+ result = run_command("ruby", "bin/mint", "edit", "nonexistent-template")
229
+
230
+ expect(result.success?).to be false
231
+ # Should provide a helpful error about the missing template
232
+ end
233
+
234
+ it "handles permission errors" do
235
+ create_markdown_file("test.md", "# Test")
236
+
237
+ # Try to publish to a location we can't write to
238
+ result = run_command({"MINT_NO_PIPE" => "1"}, "ruby", "bin/mint", "publish", "--destination", "/root", "test.md")
239
+
240
+ expect(result.success?).to be false
241
+ end
242
+ end
243
+
244
+ describe "environment handling" do
245
+ it "respects EDITOR environment variable" do
246
+ setup_basic_config
247
+ create_template_directory("test", with_layout: true)
248
+
249
+ result = run_command(
250
+ {"EDITOR" => "echo 'custom-editor'"},
251
+ "ruby", "bin/mint", "edit-layout", "test"
252
+ )
253
+
254
+ expect(result.success?).to be true
255
+ end
256
+
257
+ it "works with different working directories" do
258
+ FileUtils.mkdir_p("subdir")
259
+ Dir.chdir("subdir") do
260
+ create_markdown_file("doc.md", "# From Subdir")
261
+
262
+ result = run_command("ruby", "../bin/mint", "publish", "doc.md")
263
+
264
+ # This might require the default template to exist
265
+ # The exact behavior depends on how Mint handles paths
266
+ end
267
+ end
268
+
269
+ it "handles Ruby load path correctly" do
270
+ # The bin script should be able to find the lib directory
271
+ result = run_command("ruby", "bin/mint", "--help")
272
+
273
+ expect(result.success?).to be true
274
+ # Should not have load errors
275
+ expect(result.stderr).not_to include("LoadError")
276
+ expect(result.stderr).not_to include("cannot load such file")
277
+ end
278
+ end
279
+
280
+ describe "output formatting and verbosity" do
281
+ it "produces clean output for normal operations" do
282
+ create_markdown_file("test.md", "# Test")
283
+ setup_basic_config
284
+ create_template_directory("default")
285
+
286
+ result = run_command({"MINT_NO_PIPE" => "1"}, "ruby", "bin/mint", "publish", "test.md")
287
+
288
+ expect(result.success?).to be true
289
+ # Output should be minimal for successful operations
290
+ expect(result.stdout.length).to be < 100
291
+ end
292
+
293
+ it "provides detailed output in verbose mode" do
294
+ create_markdown_file("test.md", "# Test")
295
+ setup_basic_config
296
+ create_template_directory("default")
297
+
298
+ result = run_command({"MINT_NO_PIPE" => "1"}, "ruby", "bin/mint", "publish", "--verbose", "test.md")
299
+
300
+ # Verbose mode should provide more information
301
+ # This test depends on whether --verbose is implemented
302
+ end
303
+
304
+ it "formats template listings nicely" do
305
+ setup_basic_config
306
+ create_template_directory("template-one")
307
+ create_template_directory("template-two")
308
+
309
+ result = run_command("ruby", "bin/mint", "templates")
310
+
311
+ expect(result.success?).to be true
312
+
313
+ # Should be formatted nicely, one per line
314
+ lines = result.stdout.split("\n").reject(&:empty?)
315
+ expect(lines.length).to be >= 2
316
+ end
317
+ end
318
+
319
+ describe "integration with system tools" do
320
+ it "can be used in shell pipelines" do
321
+ create_markdown_file("input.md", "# Pipeline Test")
322
+ setup_basic_config
323
+ create_template_directory("default")
324
+
325
+ # Test that it works with shell redirection
326
+ result = run_command("bash", "-c", "MINT_NO_PIPE=1 ruby bin/mint publish input.md 2>&1")
327
+
328
+ expect(result.success?).to be true
329
+ expect(File.exist?("input.html")).to be true
330
+ end
331
+
332
+ it "exits with appropriate status codes" do
333
+ # Success case
334
+ create_markdown_file("success.md", "# Success")
335
+ setup_basic_config
336
+ create_template_directory("default")
337
+
338
+ result = run_command({"MINT_NO_PIPE" => "1"}, "ruby", "bin/mint", "publish", "success.md")
339
+ expect(result.exit_code).to eq(0)
340
+
341
+ # Failure case
342
+ result = run_command({"MINT_NO_PIPE" => "1"}, "ruby", "bin/mint", "publish", "nonexistent.md")
343
+ expect(result.exit_code).not_to eq(0)
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end