ukiryu 0.1.7 → 0.2.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ukiryu/cache.rb +6 -0
  3. data/lib/ukiryu/cache_registry.rb +64 -0
  4. data/lib/ukiryu/cli_commands/base_command.rb +6 -5
  5. data/lib/ukiryu/cli_commands/config_command.rb +7 -10
  6. data/lib/ukiryu/cli_commands/register_command.rb +27 -18
  7. data/lib/ukiryu/cli_commands/validate_command.rb +2 -2
  8. data/lib/ukiryu/command_builder.rb +83 -50
  9. data/lib/ukiryu/config.rb +13 -2
  10. data/lib/ukiryu/debug.rb +20 -9
  11. data/lib/ukiryu/definition/loader.rb +3 -3
  12. data/lib/ukiryu/errors.rb +37 -37
  13. data/lib/ukiryu/executable_locator.rb +40 -16
  14. data/lib/ukiryu/extractors/base_extractor.rb +2 -1
  15. data/lib/ukiryu/extractors/help_parser.rb +3 -0
  16. data/lib/ukiryu/logger.rb +51 -0
  17. data/lib/ukiryu/models/implementation_index.rb +2 -1
  18. data/lib/ukiryu/models/implementation_version.rb +18 -1
  19. data/lib/ukiryu/models/interface.rb +2 -1
  20. data/lib/ukiryu/models/run_environment.rb +0 -2
  21. data/lib/ukiryu/models/semantic_version.rb +174 -0
  22. data/lib/ukiryu/models/stage_metrics.rb +0 -1
  23. data/lib/ukiryu/register.rb +473 -232
  24. data/lib/ukiryu/shell/powershell.rb +192 -99
  25. data/lib/ukiryu/shell/sh.rb +4 -1
  26. data/lib/ukiryu/shell.rb +60 -2
  27. data/lib/ukiryu/tool/command_resolution.rb +2 -1
  28. data/lib/ukiryu/tool/executable_discovery.rb +14 -15
  29. data/lib/ukiryu/tool/loader.rb +543 -0
  30. data/lib/ukiryu/tool/version_detection.rb +1 -3
  31. data/lib/ukiryu/tool.rb +79 -87
  32. data/lib/ukiryu/tool_index.rb +127 -62
  33. data/lib/ukiryu/tools/base.rb +4 -2
  34. data/lib/ukiryu/type.rb +26 -15
  35. data/lib/ukiryu/version.rb +1 -1
  36. data/lib/ukiryu.rb +1 -1
  37. data/spec/fixtures/profiles/ghostscript_10.0.yaml +50 -0
  38. data/spec/fixtures/register/tools/ghostscript/default/10.0.yaml +6 -0
  39. data/spec/fixtures/register/tools/inkscape/INKSCAPE_MAN.md +444 -0
  40. data/spec/spec_helper.rb +10 -6
  41. data/spec/support/tool_helper.rb +2 -0
  42. data/spec/ukiryu/definition/loader_spec.rb +2 -2
  43. data/spec/ukiryu/executor_spec.rb +6 -3
  44. data/spec/ukiryu/models/execution_report_spec.rb +3 -2
  45. data/spec/ukiryu/models/semantic_version_spec.rb +284 -0
  46. data/spec/ukiryu/shell/powershell_integration_spec.rb +165 -0
  47. data/spec/ukiryu/shell/powershell_real_command_spec.rb +143 -0
  48. data/spec/ukiryu/shell/powershell_spec.rb +228 -60
  49. data/spec/ukiryu/tool/loader_spec.rb +148 -0
  50. data/spec/ukiryu/tool_index_spec.rb +110 -18
  51. data/spec/ukiryu/tools/ghostscript_spec.rb +242 -0
  52. data/spec/ukiryu/tools/imagemagick_spec.rb +2 -1
  53. data/spec/ukiryu/tools/inkscape_spec.rb +4 -2
  54. metadata +21 -4
  55. data/lib/ukiryu/register_auto_manager.rb +0 -342
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Ukiryu::Tool::Loader do
6
+ describe '.extract_profile_data' do
7
+ # Make private class method accessible
8
+ before { Ukiryu::Tool::Loader.singleton_class.send(:public, :extract_profile_data) }
9
+
10
+ context 'with Hash profile' do
11
+ it 'extracts basic profile fields' do
12
+ profile = {
13
+ 'name' => 'test_profile',
14
+ 'display_name' => 'Test Profile',
15
+ 'platforms' => ['windows'],
16
+ 'shells' => ['powershell'],
17
+ 'option_style' => 'single_dash_equals'
18
+ }
19
+
20
+ result = Ukiryu::Tool::Loader.extract_profile_data(profile)
21
+
22
+ expect(result[:name]).to eq('test_profile')
23
+ expect(result[:display_name]).to eq('Test Profile')
24
+ expect(result[:platforms]).to eq(['windows'])
25
+ expect(result[:shells]).to eq(['powershell'])
26
+ expect(result[:option_style]).to eq('single_dash_equals')
27
+ end
28
+
29
+ it 'extracts inherits field from hash with symbol keys' do
30
+ profile = {
31
+ name: 'windows',
32
+ platforms: ['windows'],
33
+ shells: ['powershell'],
34
+ inherits: 'unix'
35
+ }
36
+
37
+ result = Ukiryu::Tool::Loader.extract_profile_data(profile)
38
+
39
+ expect(result[:inherits]).to eq('unix')
40
+ end
41
+
42
+ it 'extracts inherits field from hash with string keys' do
43
+ profile = {
44
+ 'name' => 'windows',
45
+ 'platforms' => ['windows'],
46
+ 'shells' => ['powershell'],
47
+ 'inherits' => 'unix'
48
+ }
49
+
50
+ result = Ukiryu::Tool::Loader.extract_profile_data(profile)
51
+
52
+ expect(result[:inherits]).to eq('unix')
53
+ end
54
+
55
+ it 'extracts executable_name field' do
56
+ profile = {
57
+ 'name' => 'windows',
58
+ 'executable_name' => 'gswin64c'
59
+ }
60
+
61
+ result = Ukiryu::Tool::Loader.extract_profile_data(profile)
62
+
63
+ expect(result[:executable_name]).to eq('gswin64c')
64
+ end
65
+
66
+ it 'returns nil for missing inherits field' do
67
+ profile = {
68
+ 'name' => 'standalone',
69
+ 'platforms' => ['windows']
70
+ }
71
+
72
+ result = Ukiryu::Tool::Loader.extract_profile_data(profile)
73
+
74
+ expect(result[:inherits]).to be_nil
75
+ end
76
+ end
77
+
78
+ context 'with object profile' do
79
+ it 'extracts fields from object with accessors' do
80
+ profile_class = Class.new do
81
+ attr_reader :name, :display_name, :platforms, :shells, :option_style, :inherits, :executable_name
82
+
83
+ def initialize
84
+ @name = 'object_profile'
85
+ @display_name = 'Object Profile'
86
+ @platforms = ['linux']
87
+ @shells = ['bash']
88
+ @option_style = 'double_dash_equals'
89
+ @inherits = 'base'
90
+ @executable_name = 'custom_exe'
91
+ end
92
+ end
93
+
94
+ profile = profile_class.new
95
+ result = Ukiryu::Tool::Loader.extract_profile_data(profile)
96
+
97
+ expect(result[:name]).to eq('object_profile')
98
+ expect(result[:display_name]).to eq('Object Profile')
99
+ expect(result[:platforms]).to eq(['linux'])
100
+ expect(result[:shells]).to eq(['bash'])
101
+ expect(result[:option_style]).to eq('double_dash_equals')
102
+ expect(result[:inherits]).to eq('base')
103
+ expect(result[:executable_name]).to eq('custom_exe')
104
+ end
105
+
106
+ it 'returns nil for inherits when object does not respond to it' do
107
+ profile_class = Class.new do
108
+ attr_reader :name, :display_name, :platforms, :shells, :option_style
109
+
110
+ def initialize
111
+ @name = 'no_inherits'
112
+ @display_name = 'No Inherits'
113
+ @platforms = ['macos']
114
+ @shells = ['zsh']
115
+ @option_style = 'single_dash_space'
116
+ end
117
+ end
118
+
119
+ profile = profile_class.new
120
+ result = Ukiryu::Tool::Loader.extract_profile_data(profile)
121
+
122
+ expect(result[:inherits]).to be_nil
123
+ end
124
+ end
125
+ end
126
+
127
+ describe 'profile inheritance integration' do
128
+ # This tests the full flow: extract_profile_data -> PlatformProfile -> resolve_inheritance!
129
+ it 'preserves inherits field through the conversion process' do
130
+ Ukiryu::Tool::Loader.singleton_class.send(:public, :extract_profile_data)
131
+
132
+ # Create a minimal test that verifies the inherits field is preserved
133
+ profile_hash = {
134
+ 'name' => 'windows',
135
+ 'platforms' => ['windows'],
136
+ 'shells' => ['powershell'],
137
+ 'inherits' => 'unix'
138
+ }
139
+
140
+ extracted = Ukiryu::Tool::Loader.extract_profile_data(profile_hash)
141
+
142
+ # The inherits field should be preserved
143
+ expect(extracted[:inherits]).to eq('unix')
144
+
145
+ # This would be used by PlatformProfile.resolve_inheritance! to inherit commands
146
+ end
147
+ end
148
+ end
@@ -66,18 +66,17 @@ RSpec.describe Ukiryu::ToolIndex do
66
66
 
67
67
  describe '#find_by_interface' do
68
68
  context 'when register path is nil and default is also nil' do
69
- it 'returns nil' do
70
- # Temporarily clear the default register path
71
- original_path = Ukiryu::Register.default_register_path
72
- Ukiryu::Register.default_register_path = nil
73
-
74
- index = described_class.new(register_path: nil)
69
+ it 'returns nil when register cannot be found' do
70
+ # This test verifies behavior when no register is available
71
+ # In the new architecture, Register will always try to discover a register
72
+ # So this test now verifies that when explicitly given a nonexistent path,
73
+ # the find_by_interface returns nil
74
+
75
+ # Create an index with an explicit nonexistent path
76
+ index = described_class.new(register_path: '/nonexistent/register/path')
75
77
  metadata = index.find_by_interface(:ping)
76
78
 
77
79
  expect(metadata).to be_nil
78
-
79
- # Restore the default register path
80
- Ukiryu::Register.default_register_path = original_path
81
80
  end
82
81
  end
83
82
 
@@ -93,18 +92,12 @@ RSpec.describe Ukiryu::ToolIndex do
93
92
 
94
93
  describe '#all_tools' do
95
94
  context 'when register path is nil and default is also nil' do
96
- it 'returns empty hash' do
97
- # Temporarily clear the default register path
98
- original_path = Ukiryu::Register.default_register_path
99
- Ukiryu::Register.default_register_path = nil
100
-
101
- index = described_class.new(register_path: nil)
95
+ it 'returns empty hash when register cannot be found' do
96
+ # Create an index with an explicit nonexistent path
97
+ index = described_class.new(register_path: '/nonexistent/register/path')
102
98
  tools = index.all_tools
103
99
 
104
100
  expect(tools).to eq({})
105
-
106
- # Restore the default register path
107
- Ukiryu::Register.default_register_path = original_path
108
101
  end
109
102
  end
110
103
 
@@ -165,4 +158,103 @@ RSpec.describe Ukiryu::ToolIndex do
165
158
  expect(index.instance_variable_get(:@interface_to_tools)).to eq(old_interface_to_tools)
166
159
  end
167
160
  end
161
+
162
+ describe '#select_latest_version_by_content' do
163
+ # Make private method accessible
164
+ before { Ukiryu::ToolIndex.send(:public, :select_latest_version_by_content) }
165
+
166
+ let(:temp_dir) { Dir.mktmpdir('ukiryu_version_test') }
167
+
168
+ after do
169
+ FileUtils.rm_rf(temp_dir)
170
+ end
171
+
172
+ it 'selects version from YAML content, not filename' do
173
+ # Create two files where filename and content version are SWAPPED
174
+ # File named "9.5.yaml" but contains version: '10.0'
175
+ # File named "10.0.yaml" but contains version: '9.5'
176
+ file_nine = File.join(temp_dir, '9.5.yaml')
177
+ file_ten = File.join(temp_dir, '10.0.yaml')
178
+
179
+ File.write(file_nine, "---\nversion: '10.0'\nname: test\n")
180
+ File.write(file_ten, "---\nversion: '9.5'\nname: test\n")
181
+
182
+ index = described_class.new(register_path: '/dummy')
183
+ result = index.select_latest_version_by_content([file_nine, file_ten])
184
+
185
+ # Should return content of file with version 10.0 (file_nine),
186
+ # NOT the file named "10.0.yaml" (file_ten)
187
+ expect(result).to include("version: '10.0'")
188
+ end
189
+
190
+ it 'selects the file with highest version from content' do
191
+ file1 = File.join(temp_dir, '1.0.yaml')
192
+ file2 = File.join(temp_dir, '2.0.yaml')
193
+ file3 = File.join(temp_dir, '3.0.yaml')
194
+
195
+ File.write(file1, "---\nversion: '1.0'\nname: test\n")
196
+ File.write(file2, "---\nversion: '2.0'\nname: test\n")
197
+ File.write(file3, "---\nversion: '3.0'\nname: test\n")
198
+
199
+ index = described_class.new(register_path: '/dummy')
200
+ result = index.select_latest_version_by_content([file1, file2, file3])
201
+
202
+ expect(result).to include("version: '3.0'")
203
+ end
204
+
205
+ it 'handles Ghostscript 10.0 vs 9.5 case correctly' do
206
+ # This is the real-world case that caused the bug
207
+ file_ten = File.join(temp_dir, '10.0.yaml')
208
+ file_nine = File.join(temp_dir, '9.5.yaml')
209
+
210
+ File.write(file_ten, "---\nversion: '10.0'\nname: ghostscript\nimplements: ghostscript/1.0\n")
211
+ File.write(file_nine, "---\nversion: '9.5'\nname: ghostscript\nimplements: ghostscript/1.0\n")
212
+
213
+ index = described_class.new(register_path: '/dummy')
214
+ result = index.select_latest_version_by_content([file_nine, file_ten])
215
+
216
+ expect(result).to include("version: '10.0'")
217
+ end
218
+
219
+ it 'returns nil for empty file list' do
220
+ index = described_class.new(register_path: '/dummy')
221
+ expect(index.select_latest_version_by_content([])).to be_nil
222
+ end
223
+
224
+ it 'returns content of single file' do
225
+ file = File.join(temp_dir, '1.0.yaml')
226
+ File.write(file, "---\nversion: '1.0'\nname: test\n")
227
+
228
+ index = described_class.new(register_path: '/dummy')
229
+ result = index.select_latest_version_by_content([file])
230
+
231
+ expect(result).to include("version: '1.0'")
232
+ end
233
+
234
+ it 'skips files without version field' do
235
+ file_with_version = File.join(temp_dir, 'with_version.yaml')
236
+ file_without_version = File.join(temp_dir, 'no_version.yaml')
237
+
238
+ File.write(file_with_version, "---\nversion: '2.0'\nname: test\n")
239
+ File.write(file_without_version, "---\nname: test\n") # No version field
240
+
241
+ index = described_class.new(register_path: '/dummy')
242
+ result = index.select_latest_version_by_content([file_with_version, file_without_version])
243
+
244
+ expect(result).to include("version: '2.0'")
245
+ end
246
+
247
+ it 'skips files that cannot be parsed' do
248
+ valid_file = File.join(temp_dir, 'valid.yaml')
249
+ invalid_file = File.join(temp_dir, 'invalid.yaml')
250
+
251
+ File.write(valid_file, "---\nversion: '1.0'\nname: test\n")
252
+ File.write(invalid_file, 'this is not valid yaml [[')
253
+
254
+ index = described_class.new(register_path: '/dummy')
255
+ result = index.select_latest_version_by_content([valid_file, invalid_file])
256
+
257
+ expect(result).to include("version: '1.0'")
258
+ end
259
+ end
168
260
  end
@@ -0,0 +1,242 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe 'Ghostscript Tool Profile' do
6
+ include ToolHelper
7
+
8
+ before(:each) do
9
+ @temp_dir = create_temp_dir
10
+ end
11
+
12
+ after(:each) do
13
+ # Clean up temp directory
14
+ FileUtils.rm_rf(@temp_dir) if @temp_dir && Dir.exist?(@temp_dir)
15
+ end
16
+
17
+ # Create a simple EPS file for testing
18
+ # @param path [String] the path to create the EPS file at
19
+ def create_test_eps(path)
20
+ eps_content = <<~EPS
21
+ %!PS-Adobe-3.0 EPSF-3.0
22
+ %%BoundingBox: 0 0 100 100
23
+ %%EndComments
24
+ newpath
25
+ 0 0 moveto
26
+ 100 0 lineto
27
+ 100 100 lineto
28
+ 0 100 lineto
29
+ closepath
30
+ 0 setgray
31
+ fill
32
+ showpage
33
+ %%EOF
34
+ EPS
35
+ File.write(path, eps_content)
36
+ path
37
+ end
38
+
39
+ describe 'tool availability' do
40
+ it 'detects Ghostscript on the system' do
41
+ skip_unless_tool_available(:ghostscript)
42
+
43
+ tool = get_tool(:ghostscript)
44
+ expect(tool.available?).to be true
45
+ # Ghostscript executable names vary by platform
46
+ # Unix: gs, ghostscript
47
+ # Windows: gswin64c, gswin32c
48
+ expect(tool.executable).to match(/gs|ghostscript/i)
49
+ end
50
+ end
51
+
52
+ describe 'convert command' do
53
+ before(:each) { skip_unless_tool_available(:ghostscript) }
54
+
55
+ it 'converts EPS to PDF with -sDEVICE=pdfwrite' do
56
+ input = File.join(@temp_dir, 'input.eps')
57
+ output = File.join(@temp_dir, 'output.pdf')
58
+
59
+ create_test_eps(input)
60
+
61
+ tool = get_tool(:ghostscript)
62
+ result = tool.execute(:convert,
63
+ execution_timeout: 60,
64
+ inputs: [input],
65
+ device: :pdfwrite,
66
+ output: output,
67
+ batch: true,
68
+ no_pause: true,
69
+ quiet: true)
70
+
71
+ expect(result.success?).to be true
72
+ expect(result.exit_code).to eq(0)
73
+ expect(File.exist?(output)).to be true
74
+ # PDF should be at least 100 bytes (minimal valid PDF)
75
+ expect(File.size(output)).to be > 100
76
+ end
77
+
78
+ it 'handles -sDEVICE=pdfwrite style arguments correctly on all shells' do
79
+ # This test specifically verifies that the -sDEVICE=pdfwrite argument
80
+ # is preserved correctly on ALL shells, including PowerShell.
81
+ #
82
+ # On Windows PowerShell, arguments starting with - can be stripped by
83
+ # PowerShell's parameter binder. This test ensures the fix works by
84
+ # verifying the command succeeds and produces valid output.
85
+ input = File.join(@temp_dir, 'test.eps')
86
+ output = File.join(@temp_dir, 'test.pdf')
87
+
88
+ create_test_eps(input)
89
+
90
+ tool = get_tool(:ghostscript)
91
+
92
+ # Execute the command - if the -sDEVICE prefix was stripped,
93
+ # Ghostscript would fail with an error about unknown device
94
+ result = tool.execute(:convert,
95
+ execution_timeout: 60,
96
+ inputs: [input],
97
+ device: :pdfwrite,
98
+ output: output,
99
+ batch: true,
100
+ no_pause: true,
101
+ quiet: true)
102
+
103
+ expect(result.success?).to be true
104
+ expect(File.exist?(output)).to be true
105
+ expect(File.size(output)).to be > 100
106
+ end
107
+
108
+ it 'converts with EPS crop option' do
109
+ input = File.join(@temp_dir, 'cropped.eps')
110
+ output = File.join(@temp_dir, 'cropped.pdf')
111
+
112
+ create_test_eps(input)
113
+
114
+ tool = get_tool(:ghostscript)
115
+ result = tool.execute(:convert,
116
+ execution_timeout: 60,
117
+ inputs: [input],
118
+ device: :pdfwrite,
119
+ output: output,
120
+ batch: true,
121
+ no_pause: true,
122
+ quiet: true,
123
+ eps_crop: true)
124
+
125
+ expect(result.success?).to be true
126
+ expect(File.exist?(output)).to be true
127
+ end
128
+
129
+ it 'handles multiple dash-prefixed options correctly' do
130
+ # Test multiple options that start with dashes
131
+ # All should be preserved on all shells including PowerShell
132
+ input = File.join(@temp_dir, 'multi.eps')
133
+ output = File.join(@temp_dir, 'multi.pdf')
134
+
135
+ create_test_eps(input)
136
+
137
+ tool = get_tool(:ghostscript)
138
+
139
+ result = tool.execute(:convert,
140
+ execution_timeout: 60,
141
+ inputs: [input],
142
+ device: :pdfwrite,
143
+ output: output,
144
+ batch: true,
145
+ no_pause: true,
146
+ quiet: true,
147
+ safer: true)
148
+
149
+ expect(result.success?).to be true
150
+ expect(File.exist?(output)).to be true
151
+ end
152
+
153
+ it 'handles path with spaces' do
154
+ # Create subdirectory with space in name
155
+ subdir = File.join(@temp_dir, 'sub dir')
156
+ Dir.mkdir(subdir)
157
+ input = File.join(subdir, 'space test.eps')
158
+ output = File.join(subdir, 'space test.pdf')
159
+
160
+ create_test_eps(input)
161
+
162
+ tool = get_tool(:ghostscript)
163
+ result = tool.execute(:convert,
164
+ execution_timeout: 60,
165
+ inputs: [input],
166
+ device: :pdfwrite,
167
+ output: output,
168
+ batch: true,
169
+ no_pause: true,
170
+ quiet: true)
171
+
172
+ expect(result.success?).to be true
173
+ expect(File.exist?(output)).to be true
174
+ end
175
+ end
176
+
177
+ describe 'PowerShell-specific argument handling' do
178
+ # These tests verify the fix for PowerShell parameter binding
179
+ # which was stripping the -sDEVICE prefix from arguments
180
+ #
181
+ # PowerShell Core (pwsh) is cross-platform and available on Windows, macOS, and Linux.
182
+ # These tests can run on any platform with PowerShell and Ghostscript installed.
183
+ #
184
+ # BUG FIX: PowerShell was not quoting dash-prefixed arguments,
185
+ # causing PowerShell's parameter binder to strip the prefix.
186
+ # Example: -sDEVICE=pdfwrite became =pdfwrite
187
+ # See: lib/ukiryu/shell/powershell.rb
188
+
189
+ before(:each) do
190
+ skip_unless_tool_available(:ghostscript)
191
+ # Skip if PowerShell is not available on this system
192
+ skip 'PowerShell (pwsh) is not available' unless system('which pwsh > /dev/null 2>&1')
193
+ end
194
+
195
+ it 'preserves -sDEVICE=pdfwrite when forced to PowerShell shell' do
196
+ # Set test shell to PowerShell
197
+ original_test_shell = ENV['UKIRYU_TEST_SHELL']
198
+ ENV['UKIRYU_TEST_SHELL'] = 'powershell'
199
+
200
+ # Use the fixture register which has PowerShell in the shells list
201
+ fixture_register = File.expand_path('../../fixtures/register', __dir__)
202
+
203
+ begin
204
+ # Clear shell and tool caches to force reload with PowerShell
205
+ Ukiryu::Shell.reset
206
+ Ukiryu::Tool.clear_cache
207
+
208
+ # Set register path programmatically
209
+ Ukiryu::Register.default_register_path = fixture_register
210
+
211
+ input = File.join(@temp_dir, 'ps_test.eps')
212
+ output = File.join(@temp_dir, 'ps_test.pdf')
213
+
214
+ create_test_eps(input)
215
+
216
+ tool = Ukiryu::Tool.get('ghostscript')
217
+
218
+ # Verify PowerShell is being used
219
+ expect(Ukiryu::Shell.detect).to eq(:powershell)
220
+
221
+ result = tool.execute(:convert,
222
+ execution_timeout: 60,
223
+ inputs: [input],
224
+ device: :pdfwrite,
225
+ output: output,
226
+ batch: true,
227
+ no_pause: true,
228
+ quiet: true)
229
+
230
+ expect(result.success?).to be true
231
+ expect(File.exist?(output)).to be true
232
+ expect(File.size(output)).to be > 100
233
+ ensure
234
+ # Restore original environment
235
+ ENV['UKIRYU_TEST_SHELL'] = original_test_shell if original_test_shell
236
+ ENV.delete('UKIRYU_TEST_SHELL') unless original_test_shell
237
+ Ukiryu::Shell.reset
238
+ Ukiryu::Tool.clear_cache
239
+ end
240
+ end
241
+ end
242
+ end
@@ -112,7 +112,8 @@ RSpec.describe 'ImageMagick Tool Profile' do
112
112
  create_test_image(input)
113
113
 
114
114
  tool = get_tool(:imagemagick)
115
- result = tool.execute(:convert, execution_timeout: 30, inputs: [input], output: output, resize: '75x75', quality: 85, strip: true)
115
+ result = tool.execute(:convert, execution_timeout: 30, inputs: [input], output: output, resize: '75x75',
116
+ quality: 85, strip: true)
116
117
 
117
118
  expect(result.success?).to be true
118
119
  expect(File.exist?(output)).to be true
@@ -14,7 +14,7 @@ RSpec.describe 'Inkscape Tool Profile' do
14
14
 
15
15
  describe 'tool availability' do
16
16
  it 'detects Inkscape on the system' do
17
- skip_unless_tool_available(:inkscape)
17
+ raise 'Inkscape is not available on this system - tests must not skip, Inkscape must be installed' unless tool_available?(:inkscape)
18
18
 
19
19
  tool = get_tool(:inkscape)
20
20
  expect(tool.available?).to be true
@@ -24,7 +24,9 @@ RSpec.describe 'Inkscape Tool Profile' do
24
24
  end
25
25
 
26
26
  describe 'export command' do
27
- before(:each) { skip_unless_tool_available(:inkscape) }
27
+ before(:each) do
28
+ raise 'Inkscape is not available on this system - tests must not skip, Inkscape must be installed' unless tool_available?(:inkscape)
29
+ end
28
30
 
29
31
  it 'exports SVG to PNG' do
30
32
  input = File.join(@temp_dir, 'input.svg')