howzit 2.1.28 → 2.1.30

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.
@@ -0,0 +1,303 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Howzit::ScriptComm do
6
+ before do
7
+ Howzit.named_arguments = {}
8
+ Howzit.options[:log_level] = 0
9
+ # Clear any existing HOWZIT_COMM_FILE
10
+ ENV.delete('HOWZIT_COMM_FILE')
11
+ end
12
+
13
+ after do
14
+ # Clean up any leftover communication files
15
+ if ENV['HOWZIT_COMM_FILE'] && File.exist?(ENV['HOWZIT_COMM_FILE']) && File.file?(ENV['HOWZIT_COMM_FILE'])
16
+ begin
17
+ File.unlink(ENV['HOWZIT_COMM_FILE'])
18
+ rescue Errno::EPERM, Errno::ENOENT
19
+ # Ignore permission errors or missing files
20
+ end
21
+ end
22
+ ENV.delete('HOWZIT_COMM_FILE')
23
+ Howzit.named_arguments = {}
24
+ end
25
+
26
+ describe '.setup' do
27
+ it 'creates a communication file' do
28
+ comm_file = Howzit::ScriptComm.setup
29
+ expect(comm_file).to be_a(String)
30
+ expect(File.exist?(comm_file)).to be true
31
+ end
32
+
33
+ it 'sets HOWZIT_COMM_FILE environment variable' do
34
+ comm_file = Howzit::ScriptComm.setup
35
+ expect(ENV['HOWZIT_COMM_FILE']).to eq(comm_file)
36
+ end
37
+
38
+ it 'creates a writable file' do
39
+ comm_file = Howzit::ScriptComm.setup
40
+ expect { File.write(comm_file, 'test') }.not_to raise_error
41
+ end
42
+ end
43
+
44
+ describe '.process' do
45
+ it 'returns empty hash for non-existent file' do
46
+ result = Howzit::ScriptComm.process('/nonexistent/path')
47
+ expect(result).to eq({ logs: [], vars: {} })
48
+ end
49
+
50
+ it 'processes log messages' do
51
+ comm_file = Howzit::ScriptComm.setup
52
+ File.write(comm_file, "LOG:info:Test message\nLOG:warn:Warning message\n")
53
+ result = Howzit::ScriptComm.process(comm_file)
54
+ expect(result[:logs].length).to eq(2)
55
+ expect(result[:logs][0][:level]).to eq(:info)
56
+ expect(result[:logs][0][:message]).to eq('Test message')
57
+ expect(result[:logs][1][:level]).to eq(:warn)
58
+ expect(result[:logs][1][:message]).to eq('Warning message')
59
+ end
60
+
61
+ it 'processes variables' do
62
+ comm_file = Howzit::ScriptComm.setup
63
+ File.write(comm_file, "VAR:TEST_VAR=test_value\nVAR:ANOTHER_VAR=another_value\n")
64
+ result = Howzit::ScriptComm.process(comm_file)
65
+ expect(result[:vars]).to eq({ 'TEST_VAR' => 'test_value', 'ANOTHER_VAR' => 'another_value' })
66
+ end
67
+
68
+ it 'processes mixed logs and variables' do
69
+ comm_file = Howzit::ScriptComm.setup
70
+ File.write(comm_file, "LOG:info:Starting\nVAR:STATUS=running\nLOG:info:Done\nVAR:STATUS=complete\n")
71
+ result = Howzit::ScriptComm.process(comm_file)
72
+ expect(result[:logs].length).to eq(2)
73
+ expect(result[:vars]).to eq({ 'STATUS' => 'complete' })
74
+ end
75
+
76
+ it 'handles all log levels' do
77
+ comm_file = Howzit::ScriptComm.setup
78
+ File.write(comm_file, "LOG:info:Info message\nLOG:warn:Warn message\nLOG:error:Error message\nLOG:debug:Debug message\n")
79
+ result = Howzit::ScriptComm.process(comm_file)
80
+ expect(result[:logs].map { |l| l[:level] }).to contain_exactly(:info, :warn, :error, :debug)
81
+ end
82
+
83
+ it 'ignores empty lines' do
84
+ comm_file = Howzit::ScriptComm.setup
85
+ File.write(comm_file, "\nLOG:info:Message\n\nVAR:TEST=value\n\n")
86
+ result = Howzit::ScriptComm.process(comm_file)
87
+ expect(result[:logs].length).to eq(1)
88
+ expect(result[:vars]).to eq({ 'TEST' => 'value' })
89
+ end
90
+
91
+ it 'handles case-insensitive log levels' do
92
+ comm_file = Howzit::ScriptComm.setup
93
+ File.write(comm_file, "LOG:INFO:Uppercase\nLOG:Warn:Mixed\nLOG:error:lowercase\n")
94
+ result = Howzit::ScriptComm.process(comm_file)
95
+ expect(result[:logs].map { |l| l[:level] }).to contain_exactly(:info, :warn, :error)
96
+ end
97
+
98
+ it 'handles case-insensitive variable names' do
99
+ comm_file = Howzit::ScriptComm.setup
100
+ File.write(comm_file, "VAR:test_var=lowercase\nVAR:TEST_VAR=uppercase\n")
101
+ result = Howzit::ScriptComm.process(comm_file)
102
+ # Variable names match case-insensitively, but both are stored (last one wins)
103
+ # The regex captures the original case, so both keys are present
104
+ expect(result[:vars].keys).to include('TEST_VAR')
105
+ expect(result[:vars].keys).to include('test_var')
106
+ end
107
+
108
+ it 'removes the communication file after processing' do
109
+ comm_file = Howzit::ScriptComm.setup
110
+ File.write(comm_file, "VAR:TEST=value\n")
111
+ Howzit::ScriptComm.process(comm_file)
112
+ expect(File.exist?(comm_file)).to be false
113
+ end
114
+
115
+ it 'handles malformed lines gracefully' do
116
+ comm_file = Howzit::ScriptComm.setup
117
+ File.write(comm_file, "INVALID:line\nLOG:info:Valid message\nVAR:TEST=value\nBOGUS\n")
118
+ result = Howzit::ScriptComm.process(comm_file)
119
+ expect(result[:logs].length).to eq(1)
120
+ expect(result[:vars]).to eq({ 'TEST' => 'value' })
121
+ end
122
+
123
+ it 'handles file read errors gracefully' do
124
+ # Create a file that will cause a read error
125
+ comm_file = Howzit::ScriptComm.setup
126
+ # Make it unreadable (but this is platform-dependent, so just test that it doesn't crash)
127
+ # Instead, test with a file that doesn't exist after setup
128
+ File.unlink(comm_file) if File.exist?(comm_file)
129
+ result = Howzit::ScriptComm.process(comm_file)
130
+ expect(result).to eq({ logs: [], vars: {} })
131
+ end
132
+ end
133
+
134
+ describe '.apply' do
135
+ it 'applies log messages to console' do
136
+ comm_file = Howzit::ScriptComm.setup
137
+ File.write(comm_file, "LOG:info:Test info message\n")
138
+ expect(Howzit.console).to receive(:info).with('Test info message')
139
+ Howzit::ScriptComm.apply(comm_file)
140
+ end
141
+
142
+ it 'applies variables to named_arguments' do
143
+ comm_file = Howzit::ScriptComm.setup
144
+ File.write(comm_file, "VAR:TEST_VAR=test_value\n")
145
+ Howzit::ScriptComm.apply(comm_file)
146
+ expect(Howzit.named_arguments['TEST_VAR']).to eq('test_value')
147
+ end
148
+
149
+ it 'merges variables with existing named_arguments' do
150
+ Howzit.named_arguments = { 'EXISTING' => 'old_value' }
151
+ comm_file = Howzit::ScriptComm.setup
152
+ File.write(comm_file, "VAR:NEW_VAR=new_value\n")
153
+ Howzit::ScriptComm.apply(comm_file)
154
+ expect(Howzit.named_arguments).to eq({ 'EXISTING' => 'old_value', 'NEW_VAR' => 'new_value' })
155
+ end
156
+
157
+ it 'overwrites existing variables' do
158
+ Howzit.named_arguments = { 'TEST_VAR' => 'old_value' }
159
+ comm_file = Howzit::ScriptComm.setup
160
+ File.write(comm_file, "VAR:TEST_VAR=new_value\n")
161
+ Howzit::ScriptComm.apply(comm_file)
162
+ expect(Howzit.named_arguments['TEST_VAR']).to eq('new_value')
163
+ end
164
+
165
+ it 'handles multiple log levels' do
166
+ comm_file = Howzit::ScriptComm.setup
167
+ File.write(comm_file, "LOG:info:Info\nLOG:warn:Warn\nLOG:error:Error\nLOG:debug:Debug\n")
168
+ expect(Howzit.console).to receive(:info).with('Info')
169
+ expect(Howzit.console).to receive(:warn).with('Warn')
170
+ expect(Howzit.console).to receive(:error).with('Error')
171
+ expect(Howzit.console).to receive(:debug).with('Debug')
172
+ Howzit::ScriptComm.apply(comm_file)
173
+ end
174
+
175
+ it 'does nothing if file is empty' do
176
+ comm_file = Howzit::ScriptComm.setup
177
+ File.write(comm_file, "\n")
178
+ Howzit::ScriptComm.apply(comm_file)
179
+ expect(Howzit.named_arguments).to be_empty
180
+ end
181
+
182
+ it 'initializes named_arguments if nil' do
183
+ Howzit.named_arguments = nil
184
+ comm_file = Howzit::ScriptComm.setup
185
+ File.write(comm_file, "VAR:TEST=value\n")
186
+ Howzit::ScriptComm.apply(comm_file)
187
+ expect(Howzit.named_arguments).to eq({ 'TEST' => 'value' })
188
+ end
189
+ end
190
+
191
+ describe 'integration with Task#run_run' do
192
+ it 'processes communication file after script execution' do
193
+ # Create a temporary script that writes to communication file
194
+ script_file = Tempfile.new('test_script')
195
+ script_file.write(<<~SCRIPT)
196
+ #!/bin/bash
197
+ echo "VAR:TEST_VAR=script_value" >> "$HOWZIT_COMM_FILE"
198
+ echo "LOG:info:Script message" >> "$HOWZIT_COMM_FILE"
199
+ SCRIPT
200
+ script_file.close
201
+ File.chmod(0o755, script_file.path)
202
+
203
+ task = Howzit::Task.new({ type: :run,
204
+ title: 'Test Script',
205
+ action: script_file.path })
206
+
207
+ allow(Howzit.console).to receive(:info)
208
+ expect(Howzit.console).to receive(:info).with('Script message')
209
+
210
+ task.run
211
+
212
+ expect(Howzit.named_arguments['TEST_VAR']).to eq('script_value')
213
+
214
+ script_file.unlink
215
+ end
216
+
217
+ it 'makes variables available for subsequent tasks' do
218
+ # Create first script that sets a variable
219
+ script1 = Tempfile.new('script1')
220
+ script1.write(<<~SCRIPT)
221
+ #!/bin/bash
222
+ echo "VAR:BUILD_VERSION=1.2.3" >> "$HOWZIT_COMM_FILE"
223
+ SCRIPT
224
+ script1.close
225
+ File.chmod(0o755, script1.path)
226
+
227
+ # Create second script that uses the variable (simulated via echo)
228
+ script2 = Tempfile.new('script2')
229
+ script2.write(<<~SCRIPT)
230
+ #!/bin/bash
231
+ echo "Version would be: ${BUILD_VERSION}"
232
+ SCRIPT
233
+ script2.close
234
+ File.chmod(0o755, script2.path)
235
+
236
+ # Run first task
237
+ task1 = Howzit::Task.new({ type: :run,
238
+ title: 'Set Version',
239
+ action: script1.path })
240
+ allow(Howzit.console).to receive(:info)
241
+ task1.run
242
+
243
+ # Verify variable is set
244
+ expect(Howzit.named_arguments['BUILD_VERSION']).to eq('1.2.3')
245
+
246
+ # Create a task with variable substitution in the action
247
+ # Note: Variable substitution happens when Task is created,
248
+ # so we need to create task2 AFTER task1 runs
249
+ action_with_var = "echo Version: ${BUILD_VERSION}"
250
+ action_rendered = action_with_var.dup
251
+ action_rendered.render_named_placeholders
252
+ expect(action_rendered).to include('1.2.3')
253
+
254
+ script1.unlink
255
+ script2.unlink
256
+ end
257
+ end
258
+
259
+ describe 'integration with Task#run_block' do
260
+ it 'processes communication file after block execution' do
261
+ block_content = <<~BLOCK
262
+ #!/bin/bash
263
+ echo "VAR:BLOCK_VAR=block_value" >> "$HOWZIT_COMM_FILE"
264
+ echo "LOG:info:Block message" >> "$HOWZIT_COMM_FILE"
265
+ BLOCK
266
+
267
+ task = Howzit::Task.new({ type: :block,
268
+ title: 'Test Block',
269
+ action: block_content })
270
+
271
+ allow(Howzit.console).to receive(:info)
272
+ expect(Howzit.console).to receive(:info).with('Block message')
273
+
274
+ task.run
275
+
276
+ expect(Howzit.named_arguments['BLOCK_VAR']).to eq('block_value')
277
+ end
278
+
279
+ it 'cleans up communication file after block execution' do
280
+ comm_file_path = nil
281
+ allow(Howzit::ScriptComm).to receive(:setup).and_wrap_original do |m|
282
+ comm_file_path = m.call
283
+ comm_file_path
284
+ end
285
+
286
+ block_content = <<~BLOCK
287
+ #!/bin/bash
288
+ echo "VAR:TEST=value" >> "$HOWZIT_COMM_FILE"
289
+ BLOCK
290
+
291
+ task = Howzit::Task.new({ type: :block,
292
+ title: 'Test Block',
293
+ action: block_content })
294
+
295
+ allow(Howzit.console).to receive(:info)
296
+ task.run
297
+
298
+ # Communication file should be cleaned up
299
+ expect(File.exist?(comm_file_path)).to be false if comm_file_path
300
+ end
301
+ end
302
+ end
303
+
@@ -0,0 +1,319 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'Sequential Conditional Evaluation' do
6
+ before do
7
+ Howzit.options[:include_upstream] = false
8
+ Howzit.options[:default] = true
9
+ Howzit.options[:matching] = 'partial'
10
+ Howzit.options[:multiple_matches] = 'choose'
11
+ Howzit.options[:log_level] = 1
12
+ Howzit.named_arguments = {}
13
+ end
14
+
15
+ after do
16
+ FileUtils.rm_f('builda.md')
17
+ Howzit.named_arguments = {}
18
+ end
19
+
20
+ describe 'variables set in run blocks affecting conditionals' do
21
+ it 'allows @if blocks to use variables set in preceding run blocks' do
22
+ note = <<~EONOTE
23
+ # Test
24
+
25
+ ## Test Topic
26
+
27
+ ```run Set Variable
28
+ #!/bin/bash
29
+ echo "VAR:TEST_VAR=success" >> "$HOWZIT_COMM_FILE"
30
+ ```
31
+
32
+ @if ${TEST_VAR} == "success"
33
+ @run(echo "Conditional task executed") Conditional Task
34
+ @end
35
+ EONOTE
36
+ File.open('builda.md', 'w') { |f| f.puts note }
37
+ Howzit.instance_variable_set(:@buildnote, nil)
38
+ topic = Howzit.buildnote.find_topic('Test Topic')[0]
39
+ expect(topic).not_to be_nil
40
+
41
+ # Verify the conditional task is present
42
+ expect(topic.directives).not_to be_nil
43
+ expect(topic.directives.any?(&:conditional?)).to be true
44
+
45
+ # Run the topic and verify the conditional task executes
46
+ allow(Howzit::Prompt).to receive(:yn).and_return(true)
47
+
48
+ # Track which tasks actually run
49
+ task_titles = []
50
+ allow_any_instance_of(Howzit::Task).to receive(:run).and_wrap_original do |method|
51
+ task = method.receiver
52
+ task_titles << task.title if task.respond_to?(:title) && task.title
53
+ method.call
54
+ end
55
+
56
+ topic.run
57
+
58
+ # The conditional task should have been executed
59
+ expect(task_titles).to include('Conditional Task')
60
+ end
61
+
62
+ it 'does not execute @if blocks when variable condition is false' do
63
+ note = <<~EONOTE
64
+ # Test
65
+
66
+ ## Test Topic
67
+
68
+ ```run Set Variable
69
+ #!/bin/bash
70
+ echo "VAR:TEST_VAR=failure" >> "$HOWZIT_COMM_FILE"
71
+ ```
72
+
73
+ @if ${TEST_VAR} == "success"
74
+ @run(echo "This should not run") Hidden Task
75
+ @end
76
+ EONOTE
77
+ File.open('builda.md', 'w') { |f| f.puts note }
78
+ Howzit.instance_variable_set(:@buildnote, nil)
79
+ topic = Howzit.buildnote.find_topic('Test Topic')[0]
80
+
81
+ task_titles = []
82
+ allow(Howzit::Prompt).to receive(:yn).and_return(true)
83
+
84
+ # Track which tasks actually run
85
+ allow_any_instance_of(Howzit::Task).to receive(:run).and_wrap_original do |method|
86
+ task = method.receiver
87
+ task_titles << task.title if task.respond_to?(:title) && task.title
88
+ method.call
89
+ end
90
+
91
+ topic.run
92
+
93
+ # The conditional task should NOT have been executed
94
+ expect(task_titles).not_to include('Hidden Task')
95
+ end
96
+
97
+ it 're-evaluates conditionals after each task execution' do
98
+ note = <<~EONOTE
99
+ # Test
100
+
101
+ ## Test Topic
102
+
103
+ ```run Set First Variable
104
+ #!/bin/bash
105
+ echo "VAR:STEP=1" >> "$HOWZIT_COMM_FILE"
106
+ ```
107
+
108
+ @if ${STEP} == "1"
109
+ @run(echo "VAR:STEP=2" >> "$HOWZIT_COMM_FILE") Update Step
110
+ @end
111
+
112
+ @if ${STEP} == "2"
113
+ @run(echo "Final step") Final Task
114
+ @end
115
+ EONOTE
116
+ File.open('builda.md', 'w') { |f| f.puts note }
117
+ Howzit.instance_variable_set(:@buildnote, nil)
118
+ topic = Howzit.buildnote.find_topic('Test Topic')[0]
119
+
120
+ task_titles = []
121
+ allow(Howzit::Prompt).to receive(:yn).and_return(true)
122
+
123
+ # Track which tasks actually run
124
+ allow_any_instance_of(Howzit::Task).to receive(:run).and_wrap_original do |method|
125
+ task = method.receiver
126
+ task_titles << task.title if task.respond_to?(:title) && task.title
127
+ method.call
128
+ end
129
+
130
+ topic.run
131
+
132
+ # Both conditional tasks should execute
133
+ expect(task_titles).to include('Update Step')
134
+ expect(task_titles).to include('Final Task')
135
+ end
136
+
137
+ it 'handles @unless blocks with variables from run blocks' do
138
+ note = <<~EONOTE
139
+ # Test
140
+
141
+ ## Test Topic
142
+
143
+ ```run Set Variable
144
+ #!/bin/bash
145
+ echo "VAR:STATUS=ready" >> "$HOWZIT_COMM_FILE"
146
+ ```
147
+
148
+ @unless ${STATUS} == "not_ready"
149
+ @run(echo "Status is ready") Ready Task
150
+ @end
151
+ EONOTE
152
+ File.open('builda.md', 'w') { |f| f.puts note }
153
+ Howzit.instance_variable_set(:@buildnote, nil)
154
+ topic = Howzit.buildnote.find_topic('Test Topic')[0]
155
+
156
+ task_titles = []
157
+ allow(Howzit::Prompt).to receive(:yn).and_return(true)
158
+
159
+ # Track which tasks actually run
160
+ allow_any_instance_of(Howzit::Task).to receive(:run).and_wrap_original do |method|
161
+ task = method.receiver
162
+ task_titles << task.title if task.respond_to?(:title) && task.title
163
+ method.call
164
+ end
165
+
166
+ topic.run
167
+
168
+ expect(task_titles).to include('Ready Task')
169
+ end
170
+
171
+ it 'handles @elsif blocks with variables from run blocks' do
172
+ note = <<~EONOTE
173
+ # Test
174
+
175
+ ## Test Topic
176
+
177
+ ```run Set Variable
178
+ #!/bin/bash
179
+ echo "VAR:VALUE=two" >> "$HOWZIT_COMM_FILE"
180
+ ```
181
+
182
+ @if ${VALUE} == "one"
183
+ @run(echo "Value is one") One Task
184
+ @elsif ${VALUE} == "two"
185
+ @run(echo "Value is two") Two Task
186
+ @else
187
+ @run(echo "Value is other") Other Task
188
+ @end
189
+ EONOTE
190
+ File.open('builda.md', 'w') { |f| f.puts note }
191
+ Howzit.instance_variable_set(:@buildnote, nil)
192
+ topic = Howzit.buildnote.find_topic('Test Topic')[0]
193
+
194
+ task_titles = []
195
+ allow(Howzit::Prompt).to receive(:yn).and_return(true)
196
+
197
+ # Track which tasks actually run
198
+ allow_any_instance_of(Howzit::Task).to receive(:run).and_wrap_original do |method|
199
+ task = method.receiver
200
+ task_titles << task.title if task.respond_to?(:title) && task.title
201
+ method.call
202
+ end
203
+
204
+ topic.run
205
+
206
+ expect(task_titles).to include('Two Task')
207
+ expect(task_titles).not_to include('One Task')
208
+ expect(task_titles).not_to include('Other Task')
209
+ end
210
+
211
+ it 'handles @else blocks with variables from run blocks' do
212
+ note = <<~EONOTE
213
+ # Test
214
+
215
+ ## Test Topic
216
+
217
+ ```run Set Variable
218
+ #!/bin/bash
219
+ echo "VAR:VALUE=other" >> "$HOWZIT_COMM_FILE"
220
+ ```
221
+
222
+ @if ${VALUE} == "one"
223
+ @run(echo "Value is one") One Task
224
+ @else
225
+ @run(echo "Value is other") Other Task
226
+ @end
227
+ EONOTE
228
+ File.open('builda.md', 'w') { |f| f.puts note }
229
+ Howzit.instance_variable_set(:@buildnote, nil)
230
+ topic = Howzit.buildnote.find_topic('Test Topic')[0]
231
+
232
+ task_titles = []
233
+ allow(Howzit::Prompt).to receive(:yn).and_return(true)
234
+
235
+ # Track which tasks actually run
236
+ allow_any_instance_of(Howzit::Task).to receive(:run).and_wrap_original do |method|
237
+ task = method.receiver
238
+ task_titles << task.title if task.respond_to?(:title) && task.title
239
+ method.call
240
+ end
241
+
242
+ topic.run
243
+
244
+ expect(task_titles).to include('Other Task')
245
+ expect(task_titles).not_to include('One Task')
246
+ end
247
+ end
248
+
249
+ describe 'variables set in run blocks available in subsequent run blocks' do
250
+ it 'makes variables set in one run block available to subsequent run blocks' do
251
+ note = <<~EONOTE
252
+ # Test
253
+
254
+ ## Test Topic
255
+
256
+ ```run Set Variable
257
+ #!/bin/bash
258
+ echo "VAR:SHARED_VAR=test_value" >> "$HOWZIT_COMM_FILE"
259
+ ```
260
+
261
+ ```run Use Variable
262
+ #!/bin/bash
263
+ set_var VERIFIED "true"
264
+ ```
265
+ EONOTE
266
+ File.open('builda.md', 'w') { |f| f.puts note }
267
+ Howzit.instance_variable_set(:@buildnote, nil)
268
+ topic = Howzit.buildnote.find_topic('Test Topic')[0]
269
+
270
+ allow(Howzit::Prompt).to receive(:yn).and_return(true)
271
+
272
+ # Actually run the tasks to set variables
273
+ topic.run
274
+
275
+ # Verify the variables were set and available
276
+ expect(Howzit.named_arguments['SHARED_VAR']).to eq('test_value')
277
+ expect(Howzit.named_arguments['VERIFIED']).to eq('true')
278
+ end
279
+
280
+ it 'allows multiple run blocks to set and use variables sequentially' do
281
+ note = <<~EONOTE
282
+ # Test
283
+
284
+ ## Test Topic
285
+
286
+ ```run First Block
287
+ #!/bin/bash
288
+ echo "VAR:FIRST=1" >> "$HOWZIT_COMM_FILE"
289
+ ```
290
+
291
+ ```run Second Block
292
+ #!/bin/bash
293
+ set_var SECOND "2"
294
+ set_var COMBINED "12"
295
+ ```
296
+
297
+ ```run Third Block
298
+ #!/bin/bash
299
+ set_var THIRD "3"
300
+ set_var ALL "123"
301
+ ```
302
+ EONOTE
303
+ File.open('builda.md', 'w') { |f| f.puts note }
304
+ Howzit.instance_variable_set(:@buildnote, nil)
305
+ topic = Howzit.buildnote.find_topic('Test Topic')[0]
306
+
307
+ allow(Howzit::Prompt).to receive(:yn).and_return(true)
308
+
309
+ # Actually run the tasks to set variables sequentially
310
+ topic.run
311
+
312
+ expect(Howzit.named_arguments['FIRST']).to eq('1')
313
+ expect(Howzit.named_arguments['SECOND']).to eq('2')
314
+ expect(Howzit.named_arguments['COMBINED']).to eq('12')
315
+ expect(Howzit.named_arguments['THIRD']).to eq('3')
316
+ expect(Howzit.named_arguments['ALL']).to eq('123')
317
+ end
318
+ end
319
+ end