Ifd_Automation 2.9 → 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/Ifd_Automation/REST_steps.rb +33 -33
  3. data/lib/Ifd_Automation/SOAP_steps.rb +31 -31
  4. data/lib/Ifd_Automation/assertion_helper.rb +97 -0
  5. data/lib/Ifd_Automation/auto_util.rb +161 -0
  6. data/lib/Ifd_Automation/database_helper.rb +78 -0
  7. data/lib/Ifd_Automation/database_steps.rb +44 -44
  8. data/lib/Ifd_Automation/dynamic_store_value_steps.rb +18 -18
  9. data/lib/Ifd_Automation/email_steps.rb +31 -31
  10. data/lib/Ifd_Automation/file_helper.rb +33 -0
  11. data/lib/Ifd_Automation/file_steps.rb +9 -9
  12. data/lib/Ifd_Automation/mail_helper.rb +56 -0
  13. data/lib/Ifd_Automation/require_libs.rb +9 -9
  14. data/lib/Ifd_Automation/rest_helper.rb +89 -0
  15. data/lib/Ifd_Automation/soap_helper.rb +57 -0
  16. data/lib/Ifd_Automation/ssh_helper.rb +37 -0
  17. data/lib/Ifd_Automation/ssh_steps.rb +15 -15
  18. data/lib/{helper → Ifd_Automation}/step_fallback.rb +0 -0
  19. data/lib/{helper → Ifd_Automation}/tolerance_for_selenium_sync_issues.rb +0 -0
  20. data/lib/Ifd_Automation/version.rb +1 -1
  21. data/lib/{helper → Ifd_Automation}/web_steps_helper.rb +419 -40
  22. data/project/Gemfile +1 -1
  23. data/project/features/TestSuite/WebGUI.feature +4 -4
  24. data/project/features/step_definitions/lib_steps/steps_definition.rb +4 -2
  25. data/project/features/step_definitions/repositories/project_object.yml +2 -1
  26. metadata +13 -13
  27. data/lib/helper/assertion_helper.rb +0 -100
  28. data/lib/helper/auto_util.rb +0 -164
  29. data/lib/helper/database_helper.rb +0 -81
  30. data/lib/helper/file_helper.rb +0 -36
  31. data/lib/helper/mail_helper.rb +0 -58
  32. data/lib/helper/rest_helper.rb +0 -91
  33. data/lib/helper/soap_helper.rb +0 -59
  34. data/lib/helper/ssh_helper.rb +0 -39
@@ -1,100 +0,0 @@
1
- class IFD_Assertion
2
- #Assert two files, rows not in order and REMOVE 1 COLUMN OF ID
3
- def self.do_assertion_csv_tab_non_order(expected_obj, actual_obj)
4
- for i in (1..expected_obj.length - 1)
5
- expected_row = expected_obj[i].drop(1).to_s.split("\t")
6
- found = false
7
- for j in (1..actual_obj.length - 1)
8
- actual_row = actual_obj[j].drop(1).to_s.split("\t")
9
- if (expected_row == actual_row)
10
- found = true
11
- break
12
- end
13
- end
14
- assert(found, "Expected Record: [#{expected_obj[i].to_s}] is not included in reporting file")
15
- end
16
- end
17
-
18
- # Assert 2 values
19
- def self.reg_compare sActual, regValue, isSpecialChar=false
20
- begin
21
- if !isSpecialChar
22
- sActual = sActual.strip
23
- regValue = regValue.strip.gsub("[", "\\[").gsub("]", "\\]").gsub("(", "\\(").gsub(")", "\\)").gsub(">", "\\>")
24
- end
25
- rescue StandardError => myStandardError
26
- put_log "\n>>> Error: #{myStandardError}"
27
- end
28
-
29
- # put_log "\nsActual:#{sActual}, regValue:#{regValue}"
30
- if ((sActual.nil? and regValue.nil?) or (!sActual.nil? and sActual.empty? and !regValue.nil? and regValue.empty?))
31
- return true
32
- end
33
-
34
- if ((sActual.nil? and !regValue.nil?) or (!sActual.nil? and regValue.nil?))
35
- return false
36
- end
37
-
38
- if (!sActual.nil? and !sActual.empty?)
39
- sCookActual = sActual.gsub(/\n|\r/, " ")
40
- if (sCookActual == regValue or (isSpecialChar and sCookActual.include? regValue) or (!isSpecialChar and sCookActual =~ /^.*#{regValue}.*$/))
41
- return true
42
- end
43
- end
44
-
45
- return false
46
- end
47
-
48
- def self.do_assertion_json(expected_obj, actual_obj, options = {})
49
- # puts "\n\n actual_obj.class: #{actual_obj.class}"
50
- # puts "\n\n expected_obj.class: #{expected_obj.class}"
51
-
52
- if expected_obj.kind_of? Hash
53
- # if options['isIncludedAssertion'].nil? or options['isIncludedAssertion'] == false
54
- # do_assertion(expected_obj.keys.size, actual_obj.keys.size)
55
- # end
56
- expected_obj.keys.each do |key|
57
- # puts "\n\n key: #{key}"
58
- # puts "\n\n value: #{expected_obj[key]}"
59
- # puts "\n\n value: #{actual_obj[key]}"
60
- if actual_obj[key].nil?
61
- raise "[%s] expected [%s] but actual value was nil." % [key, expected_obj[key].to_s]
62
- else
63
- IFD_Assertion.do_assertion_json(expected_obj[key], actual_obj[key], options)
64
- end
65
- end
66
- elsif expected_obj.kind_of? Array
67
- if options['isIncludedAssertion'].nil? or options['isIncludedAssertion'] == false
68
- IFD_Assertion.do_assertion_json(expected_obj.size, actual_obj.size)
69
- end
70
- for i in (0..expected_obj.length-1)
71
- IFD_Assertion.do_assertion_json(expected_obj[i], actual_obj[i], options)
72
- end
73
- else
74
- begin
75
- IFD_Assertion.assert_string_equal(expected_obj.to_s, actual_obj.to_s)
76
- rescue => e
77
- raise("Assert fail. \n\n Expected: '#{expected_obj}' \n\n Got: '#{actual_obj}'. Detail info: #{e.message}")
78
- end
79
- end
80
- end
81
-
82
- def self.assert_string_contain(expected, actual)
83
- unless (actual.to_s).include? (expected.to_s)
84
- raise ("*** ASSERTION ERROR: \nExpected: #{expected}. \nGot: #{actual}.")
85
- end
86
- end
87
-
88
- def self.assert_string_equal(expected, actual)
89
- if expected.to_s != actual.to_s
90
- raise ("*** ASSERTION ERROR: \nExpected: #{expected}. \nGot: #{actual}.")
91
- end
92
- end
93
-
94
- def self.assert_string_not_equal(expected, actual)
95
- if expected.to_s == actual.to_s
96
- raise ("*** ASSERTION ERROR: \nExpected: #{expected}. \nGot: #{actual}.")
97
- end
98
- end
99
-
100
- end
@@ -1,164 +0,0 @@
1
- class Utils
2
- #-----------------------------------------------------
3
- # support define and bind variable dynamically
4
- #-----------------------------------------------------
5
- $dyn_vars = nil
6
-
7
- # set value to a variable
8
- def self.set_var(var_name, var_value)
9
- if $dyn_vars == nil
10
- $dyn_vars = binding
11
- end
12
-
13
- strEval = var_name + "=" + var_value
14
- eval strEval, $dyn_vars
15
- end
16
-
17
- def self.check_dynamic_value value
18
- if !value.is_a? Fixnum
19
- if value.include? "params="
20
- resolve_params value
21
- else
22
- bind_with_dyn_vars value
23
- end
24
- else
25
- value
26
- end
27
- end
28
-
29
-
30
- def self.resolve_params url
31
- condition = url.match(/params='([^']*)'/)[0]
32
- if condition
33
- params_name = url.match(/params='([^']*)'/)[1]
34
- params_value = $PARAMS["#{params_name.downcase}"].to_s.strip
35
- if params_value.present?
36
- url = url.gsub(condition, params_value)
37
- else
38
- raise "ERROR: no data found with given params #{params_name}"
39
- end
40
- end
41
- url
42
- end
43
-
44
- # bind string with $dyn_vars context
45
- def self.bind_with_dyn_vars(str)
46
- if $dyn_vars == nil
47
- $dyn_vars = binding
48
- end
49
-
50
- strEval = '"' + str + '"'
51
- return eval strEval, $dyn_vars
52
- end
53
-
54
- # evaluate operation/statement with $dyn_vars context
55
- def self.eval_with_dyn_vars(operation)
56
- if $dyn_vars == nil
57
- $dyn_vars = binding
58
- end
59
-
60
- eval operation, $dyn_vars
61
- end
62
-
63
- def self.bind_with_dyn_json_vars(json, bind_json)
64
- if json.kind_of? Hash
65
- json.each_pair do |k, v|
66
- if v.kind_of? String
67
- bind_json[bind_with_dyn_vars(k)] = bind_with_dyn_json_vars(v, bind_json)
68
- elsif v.kind_of? Hash
69
- temp = Hash.new
70
- v.each_pair do |k1, v1|
71
- temp[bind_with_dyn_vars(k1)] = bind_with_dyn_json_vars(v1, temp)
72
- end
73
- bind_json[bind_with_dyn_vars(k)] = temp
74
- elsif v.kind_of? Array
75
- temp1 = Array.new
76
- v.each { |item|
77
- temp2 = Hash.new
78
- bind_with_dyn_json_vars(item, temp2)
79
- temp1 << temp2
80
- }
81
- bind_json[bind_with_dyn_vars(k)] = temp1
82
- end
83
- end
84
- elsif json.kind_of? Array
85
- temp1 = Array.new
86
- json.each { |item|
87
- temp2 = Hash.new
88
- bind_with_dyn_json_vars(item, temp2)
89
- temp1 << temp2
90
- }
91
- return temp1
92
- else
93
- return bind_with_dyn_vars(json)
94
- end
95
- end
96
-
97
-
98
- def self.var_collect string_var
99
- if string_var =~ /^.*{year}.*$/
100
- string_var = replace_year(string_var)
101
- end
102
-
103
- if string_var =~ /^.*{month}.*$/
104
- string_var = replace_month(string_var)
105
- end
106
-
107
- if string_var =~ /^.*{day}.*$/
108
- string_var = replace_day(string_var)
109
- end
110
-
111
- if string_var =~ /^.*{store_value}.*$/
112
- string_var = $context_value
113
- end
114
-
115
- return string_var
116
- end
117
-
118
- def self.replace_year str
119
- t = Time.now()
120
- return str.gsub("{year}", t.year.to_s)
121
- end
122
-
123
- def replace_month str
124
- t = Time.now()
125
- _month = t.month
126
- if _month < 10
127
- return str.gsub("{month}", "0#{_month.to_s}")
128
- else
129
- return str.gsub("{month}", "#{_month.to_s}")
130
- end
131
- return str
132
- end
133
-
134
- def self.replace_day str
135
- t = Time.now()
136
- _day = t.day
137
- if _day < 10
138
- return str.gsub("{day}", "0#{_day.to_s}")
139
- else
140
- return str.gsub("{day}", "#{_day.to_s}")
141
- end
142
- return str
143
- end
144
-
145
- def self.replace_pipe str_pipe
146
- put_log ">>>> #{str_pipe}"
147
- if str_pipe =~ /^.*{pipe}.*$/
148
- return str_pipe.gsub("{pipe}", "|")
149
- end
150
- return str_pipe
151
- end
152
-
153
- def self.store_string_as_variable(string,variable)
154
- # $context_value = Utils.bind_with_dyn_vars(string)
155
- # Utils.set_var(variable, '$context_value')
156
- require 'erb'
157
- ERB.new(string, 0, "", "#{variable}").result(binding)
158
- end
159
-
160
- def self.print_variable(variable)
161
- puts "VALUE OF #{variable}: #{Utils.eval_with_dyn_vars(variable)}"
162
- end
163
-
164
- end
@@ -1,81 +0,0 @@
1
- require 'tiny_tds'
2
- require 'activerecord-sqlserver-adapter'
3
- require 'active_record'
4
-
5
- module IFD_DBConnection
6
- def self.new(connection_params)
7
- begin
8
- put_log ("Connecting to database...")
9
- return ActiveRecord::Base.establish_connection(connection_params)
10
- rescue Exception => e
11
- raise e.message
12
- end
13
- end
14
-
15
- def self.create_database_connection(data)
16
- unless data.hashes.empty?
17
- data = data.hashes[0]
18
- data = JSON.parse(data) unless data.is_a? Hash
19
-
20
- data.each_pair do |k, v|
21
- data[k] = Utils.check_dynamic_value(v)
22
- end
23
- @connection = IFD_DBConnection.new(data)
24
- put_log "Connect to database successfully!" if @connection
25
- end
26
- end
27
-
28
- def self.close_database_connection
29
- @connection.disconnect!
30
- if !@connection.connected?
31
- put_log "Disconnected to Database!"
32
- end
33
- end
34
-
35
- def self.execute_select(script)
36
- script = Utils.check_dynamic_value(script)
37
- if @connection
38
- @result = @connection.connection.exec_query(script)
39
- else
40
- raise "ERROR: Create connection to database first!"
41
- end
42
- end
43
-
44
- def self.execute_script(script)
45
- script = Utils.check_dynamic_value(script)
46
- if @connection
47
- @result = @connection.connection.execute(script)
48
- else
49
- raise "ERROR: Create connection to database first!"
50
- end
51
- end
52
-
53
- def self.print_sql_result
54
- if @result.present?
55
- @result.each do |row|
56
- p row
57
- end
58
- else
59
- p "WARNING: No result from SQL statement"
60
- end
61
- end
62
-
63
- def self.verify_sql_result_with_json(json)
64
- expected = JSON.parse(json)
65
- @result.each do |row|
66
- IFD_Assertion.assert_string_equal(expected,row)
67
- end
68
- end
69
-
70
- def self.verify_sql_result_with_json_node(json_node, value)
71
- @result.each do|row|
72
- results = JsonPath.new(json_node).on(row).to_a.map(&:to_s)
73
- IFD_Assertion.assert_string_equal(results[0], value)
74
- end
75
- end
76
-
77
- def self.store_sql_result_into_string(string)
78
- Utils.set_var(string, @result)
79
- end
80
-
81
- end
@@ -1,36 +0,0 @@
1
- class IFD_File
2
-
3
- def self.delete_file(file_name)
4
- file_path = ($test_data_dir + file_name.gsub(" ", "_"))
5
- if File.exists?(file_path)
6
- File.delete(file_path)
7
- puts "#{file_name} is deleted successfully"
8
- else
9
- puts "File #{file_name} does not exists"
10
- end
11
- end
12
-
13
- def self.read_file(file_name)
14
- @file_data = ""
15
- file_path = $test_data_dir + file_name.downcase
16
- if File.exist?(file_path)
17
- file = File.open(file_path)
18
- @file_data += file.read
19
- file.close
20
- else
21
- raise "*** WARNING: File #{file_name} does not exist."
22
- end
23
- p @file_data
24
- end
25
-
26
- def self.execute_windows_file(filename, file_location)
27
- file = file_location + filename
28
- p file
29
- if File.exist? file
30
- system("'"+file+"'")
31
- else
32
- raise "*** ERROR: File #{file} is not existed."
33
- end
34
- end
35
-
36
- end
@@ -1,58 +0,0 @@
1
- require 'mail'
2
- # require 'email_spec'
3
- # include EmailSpec::Helpers
4
- # include EmailSpec::Matcher
5
- class IFD_Email
6
-
7
- def self.send_email(raw_data)
8
- include Mail::Matchers
9
- raw_data.strip!
10
- header, body = raw_data.split(/\n\n/, 2) # 2: maximum number of fields
11
- conditions = {}
12
- header.split("\n").each do |row|
13
- if row.lstrip.chop.match(/^[a-z\-]+:/i)
14
- key, value = row.split(":", 2)
15
- conditions[key.gsub(' ','').underscore.to_sym] = value.gsub(' ','')
16
-
17
- end
18
- end
19
- conditions[:body] = body if body
20
- filepath = ($test_data_dir + conditions[:attachments] if conditions[:attachments])
21
- # Mail::TestMailer.deliveries.clear
22
- Mail.deliver do
23
- from "abc@gmail.com"
24
- to to_address if conditions[:to]
25
- subject subject if conditions[:subject]
26
- body body_email if conditions[:body]
27
- add_file attachments if filepath
28
- end
29
- end
30
-
31
- def self.verify_receive_email(raw_data)
32
- raw_data.strip!
33
- header, body = raw_data.split(/\n\n/, 2) # 2: maximum number of fields
34
- conditions = {}
35
- header.split("\n").each do |row|
36
- if row.lstrip.chop.match(/^[a-z\-]+:/i)
37
- key, value = row.split(":", 2)
38
- conditions[key.gsub(' ','').underscore.to_sym] = value.gsub(' ','')
39
-
40
- end
41
- end
42
- conditions[:body] = body.squeeze(' ').strip if body
43
- sleep 5
44
- emails = Mail.find(:what => :last, :count => 1)
45
-
46
- if emails.instance_of? Mail::Message
47
- IFD_Assertion.assert_string_equal(conditions[:from], emails.from[0].to_s)
48
- IFD_Assertion.assert_string_equal(conditions[:subject], emails.subject)
49
- IFD_Assertion.assert_string_contain(conditions[:body], emails.body)
50
- emails.attachments.each do |attachment|
51
- IFD_Assertion.assert_string_equal(conditions[:attachments], attachment.filename)
52
- end if conditions[:attachments]
53
- else
54
- raise "WARNING: *** No new Email is found"
55
- end
56
- end
57
-
58
- end
@@ -1,91 +0,0 @@
1
- require 'httparty'
2
- class IFD_Rest
3
- def self.set_headers(data)
4
- unless data.hashes.empty?
5
- data = data.hashes[0]
6
- data = JSON.parse(data) unless data.is_a? Hash
7
-
8
- data.each_pair do |k, v|
9
- data[k] = Utils.check_dynamic_value(v)
10
- end
11
- @header = data
12
- end
13
- p "HEADER: #{@header}"
14
- end
15
-
16
- def self.get_rest_result
17
- if @response.nil?
18
- p "WARNING***: MISSING STEPS: Please send a REST request to get response first."
19
- end
20
- @response
21
- end
22
-
23
- def self.store_json_node_result(json_node,string)
24
- $context_value = JsonPath.new(json_node).on(IFD_Rest.get_rest_result.body).to_a.map(&:to_s)[0]
25
- Utils.set_var(string, '$context_value')
26
- end
27
-
28
- def self.print_rest_code
29
- puts "REST RESULT code: #{IFD_Rest.get_rest_result.code}"
30
- end
31
-
32
- def self.get_rest_body
33
- puts "REST RESULT body: #{IFD_Rest.get_rest_result.body}"
34
- end
35
-
36
- def self.verify_rest_response_code(code)
37
- IFD_Assertion.assert_string_equal(code, IFD_Rest.get_rest_result.code.to_s)
38
- end
39
-
40
- def self.verify_response_body_with_json(json)
41
- IFD_Assertion.assert_string_equal(json, IFD_Rest.get_rest_result.body.to_s)
42
- end
43
-
44
- def self.verify_response_at_json_node(json_node,string)
45
- result = JsonPath.new(json_node).on(IFD_Rest.get_rest_result.body).to_a.map(&:to_s)
46
- IFD_Assertion.assert_string_equal(string, result[0])
47
- end
48
-
49
- def self.send_request(*args)
50
- request_type = args.shift.downcase
51
- url = Utils.check_dynamic_value(args.shift)
52
- put_log "Request URL: #{url}"
53
- json_payload = args.shift
54
- if json_payload
55
- payload = Hash.new
56
- JSON.parse(json_payload).each do |k1, v1|
57
- payload[Utils.check_dynamic_value(k1)] = Utils.check_dynamic_value(v1)
58
- end
59
- payload = payload.to_json
60
- end
61
- put_log "Data Body from #{request_type} method: #{payload}"
62
-
63
- if (payload.nil? && request_type == 'get' && @header.nil?)
64
- @response = Request.get(url)
65
- elsif (payload.nil? && request_type == 'get')
66
- @response = Request.get(url, {headers: @header})
67
- elsif (payload.nil? && request_type == 'delete' && @header.nil?)
68
- @response = Request.delete(url)
69
- elsif (payload.nil? && request_type == 'delete')
70
- @response = Request.delete(url, {headers: @header})
71
- elsif (payload && request_type == 'get' && @header.nil?)
72
- @response = Request.get(url, {body: payload})
73
- elsif (payload && request_type == 'get')
74
- @response = Request.get(url, {body: payload, headers: @header})
75
- elsif (payload && request_type == 'post' && @header.nil?)
76
- @response = Request.post(url, {body: payload})
77
- elsif (payload && request_type == 'post')
78
- @response = Request.post(url, {body: payload, headers: @header})
79
- elsif (payload && request_type == 'put' && @header.nil?)
80
- @response = Request.put(url, {body: payload})
81
- elsif (payload && request_type == 'put')
82
- @response = Request.put(url, {body: payload, headers: @header})
83
- end
84
- end
85
-
86
- end
87
-
88
- class Request
89
- include HTTParty
90
- default_options.update(verify: false)
91
- end
@@ -1,59 +0,0 @@
1
- require 'savon'
2
- require 'jsonpath'
3
-
4
- class IFD_Soap
5
- def self.get_soap_operation_list(url)
6
- request_url = URI.encode Utils.check_dynamic_value url
7
- @SOAPclient = Savon.client(ssl_verify_mode: :none,
8
- wsdl: "#{request_url}",
9
- :open_timeout => 10,
10
- :read_timeout => 10,
11
- :log => false)
12
- p "Operations List: #{@SOAPclient.operations}"
13
- end
14
-
15
- def self.call_and_fail_gracefully(client, *args, &block)
16
- if client.nil?
17
- raise "ERROR***: MISSING STEPS: Please run step to get operation list from WSDL first."
18
- else
19
- client.call(*args, &block)
20
- end
21
- rescue Savon::SOAPFault => e
22
- raise e.message
23
- end
24
-
25
- def self.get_soap_response
26
- soap_response = @response
27
- if soap_response.nil?
28
- raise "ERROR***: MISSING STEPS: Please send SOAP request to get the response first."
29
- else
30
- soap_response
31
- end
32
- soap_response
33
- end
34
-
35
- def self.send_soap_with_operation_and_xml(operation,file_name)
36
- xml = File.read($test_data_dir + file_name)
37
- @response = IFD_Soap.call_and_fail_gracefully(@SOAPclient, operation.downcase.to_sym, xml: xml )
38
- end
39
-
40
- def self.send_soap_with_operation_and_data(operation,data)
41
- xml = Utils.bind_with_dyn_vars(data)
42
- @response = IFD_Soap.call_and_fail_gracefully(@SOAPclient, operation.downcase.to_sym, xml: xml )
43
- end
44
-
45
- def self.verify_response_with_json_node(json_node,string)
46
- json = IFD_Soap.get_soap_response.body.to_json
47
- results = JsonPath.new(json_node).on(json).to_a.map(&:to_s)
48
- IFD_Assertion.assert_string_equal(string, results[0])
49
- end
50
-
51
- def self.verify_response_code(status_code)
52
- IFD_Assertion.assert_string_equal(IFD_Soap.get_soap_response.http.code, status_code.to_i)
53
- end
54
-
55
- def self.print_response
56
- p "SOAP RESPONSE: #{IFD_Soap.get_soap_response}"
57
- end
58
-
59
- end
@@ -1,39 +0,0 @@
1
- require 'net/ssh'
2
-
3
- class IFD_Ssh
4
- def self.connect_to_server_with_credential(host_name,table)
5
- hostname = Utils.check_dynamic_value host_name
6
- @keys = []
7
- @auth_methods ||= %w(password)
8
- session = table.hashes.first
9
- session_keys = Array.new(@keys)
10
- session_auth_methods = Array.new(@auth_methods)
11
- if session["keyfile"]
12
- session_keys << session["keyfile"]
13
- session_auth_methods << "publickey"
14
- end
15
-
16
- @SSHconnection = Net::SSH.start(hostname, session["username"], :password => session["password"],
17
- :auth_methods => session_auth_methods,
18
- :keys => session_keys)
19
- end
20
-
21
- def self.exec_command(command)
22
- command = Utils.check_dynamic_value command
23
- @output = @SSHconnection.exec!(command)
24
- end
25
-
26
- def self.print_output
27
- p @output
28
- end
29
-
30
- def self.verify_output(string)
31
- string = Utils.check_dynamic_value(string)
32
- IFD_Assertion.assert_string_equal(string, @output.strip)
33
- end
34
-
35
- def self.store_result_string(name)
36
- $context_value = Utils.bind_with_dyn_vars(@output)
37
- Utils.set_var(name, '$context_value')
38
- end
39
- end