butler-mainframe 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c5b3e86c2581052e59a8f1e74ff1da11a09ebb3c
4
- data.tar.gz: ddb71edc9e79c6b0a487e975f9bf9b2074b80beb
3
+ metadata.gz: 5dd2c3f32dca8f7e61d0ed59e11d59a158f7ff21
4
+ data.tar.gz: bc1a34ae83ca18147105f6ada19bf936cc36a417
5
5
  SHA512:
6
- metadata.gz: 542c1c9854d0163f5562cbc1bf2216ddf5294599362c8a8dc27d8fa2aeb82798c6d12c0dac9b8d2aaec842f3c71628306432e64a45ef3df1b234eacf471a381c
7
- data.tar.gz: 2a176d220c4f589313277eb8674c255ce1fff43e0d61a004e8919f9b0406ea0885d0a9cc1e04c59dadfa77fa10c461de0805ad5ea11769c0d49355f2699cf17a
6
+ metadata.gz: c9dad70f5096a1bc38d53d8e5e9e3176e09ca29452d741e1c1f25158e3e471212227f4276d0d1016ab8f7e836476dadcd9d8b0528a986f05481debbf4b539067
7
+ data.tar.gz: dfeabba225bcbe7d395ce8cc0c7bf53f4a998c1cea8b4686489362a4b228f0e5ee796114d8850db079ceb8a2b53cc07edb94b268f8efe8a0ec5389614f893e32
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ 0.6.0 [☰](https://github.com/marcomd/butler-mainframe/compare/v0.5.0...v0.6.0) October 29th, 2015
2
+ ------------------------------
3
+ * Improved rails integration
4
+ * Added rails model test with the scaffold generator, see documentation
5
+ * Added env parameter in the configuration file
6
+ * Several little improvements
7
+
1
8
  0.5.0 [☰](https://github.com/marcomd/butler-mainframe/compare/v0.4.0...v0.5.0) October 26th, 2015
2
9
  ------------------------------
3
10
  * Moved sensible parameters in a separate yml file (private.yml) do not share it
data/README.md CHANGED
@@ -160,7 +160,7 @@ My advice is to use navigate method for generic navigation and use a specific mo
160
160
 
161
161
  ## With Rails
162
162
 
163
- This module can be use on rails project.
163
+ This gem can be use on rails project.
164
164
  Add in your gemfile
165
165
 
166
166
  gem 'butler-mainframe'
@@ -169,11 +169,11 @@ then
169
169
 
170
170
  bundle install
171
171
 
172
- run generator to copy configuration files suitable for the emulator you need
172
+ run generator to copy configuration files passing your emulator as parameter (default x3270)
173
173
 
174
- rails g butler:install --emulator=passport
174
+ rails g butler:install --emulator=pcomm
175
175
 
176
- You should have a model for every function to perform.
176
+ My advice is to have a model for every function.
177
177
  In this simple example i have to insert an invoice number on a cics map so i create the invoice model:
178
178
 
179
179
  rails generate scaffold invoice number:integer
@@ -222,12 +222,49 @@ Class Invoice
222
222
  end
223
223
  ```
224
224
 
225
- Massive uses or one shot depends on your needs.
226
- The uses are many and only limited by your imagination!
227
- Experiment and you'll find the solution right for you :rocket:
225
+ If massive uses or one shot depends on your needs and according to these must be optimized the function.
228
226
 
227
+ The uses are many and only limited by your imagination! :rocket:
229
228
 
230
- ## Test with rake
229
+ Experiment and you'll find the solution right for you
230
+
231
+ ## Test
232
+
233
+ ### Test models with rails
234
+
235
+ Add the butler test helper in yours rails config/application.rb before create the resource.
236
+ In this way will be added for you the test cases for that model.
237
+ Available only for the test unit framework.
238
+
239
+ ```ruby
240
+ config.generators do |g|
241
+ ...
242
+ g.test_framework :test_unit
243
+ g.helper :butler_mainframe_test
244
+ end
245
+ ```
246
+
247
+ For example if you created the invoice resource:
248
+
249
+ With rails 4:
250
+
251
+ rake test test\models\butler_mainframe_invoice_test.rb
252
+
253
+ Rails 3 is not tested yet:
254
+
255
+ ruby -I test unit butler_mainframe_invoice_test.rb
256
+
257
+ You should get something like this:
258
+
259
+ ** Connection established with PComm A **
260
+ ...
261
+ Session closed because started by this process with id 1234
262
+
263
+ Finished in 13.044988s, 0.1533 runs/s, 0.3066 assertions/s.
264
+
265
+ 2 runs, 4 assertions, 0 failures, 0 errors, 0 skips
266
+
267
+ ### Test with rake
231
268
 
232
269
  Simple embedded tests
233
270
 
@@ -8,7 +8,6 @@
8
8
 
9
9
  require 'core/configuration'
10
10
  require 'core/configuration_dynamic'
11
- require 'config/config'
12
11
 
13
12
  module ButlerMainframe
14
13
  def self.root
@@ -16,49 +15,28 @@ module ButlerMainframe
16
15
  end
17
16
  end
18
17
 
19
- # TODO
20
- # require 'i18n'
21
- # I18n.load_path=Dir['config/locales/*.yml']
22
- # I18n.locale = ButlerMainframe.configuration.language
18
+ # This project use monkey patch for 1.8 compatibility
19
+ require 'mainframe/host_base'
23
20
 
24
- env = Rails.env if defined?(Rails)
25
- env ||= $ARGV[0] if $ARGV
26
- env ||= "development"
27
- debug = env == "development" ? true : false
21
+ # puts "Butler Mainframe #{defined?(Rails) ? 'with' : 'without'} Rails" #DEBUG
22
+ if defined?(Rails)
23
+ # Rails use own configuration file into initializers folder
28
24
 
29
- # require the emulator sub class specified in the config.rb
30
- require "mainframe/emulators/#{ButlerMainframe.configuration.host_gateway.to_s.downcase}"
31
-
32
-
33
- %w(settings.yml private.yml).each do |file|
34
- filepath = File.join(ButlerMainframe.root,'lib','config',file)
35
- ButlerMainframe::Settings.load!(filepath, :env => env) if File.exist? filepath
36
- end
37
-
38
- require 'mainframe/customization/active_record'
39
- # puts "Extending Host class with #{Host3270::ActiveRecord}" if debug
40
- # Use monkey patch for 1.8 compatibility
41
- class ButlerMainframe::Host
42
- include Host3270::ActiveRecord
43
- end
25
+ # This module adds additional methods useful only for projects rails
26
+ require 'mainframe/customization/active_record'
27
+ class ButlerMainframe::HostBase
28
+ include ButlerMainframe::ActiveRecord
29
+ end
30
+ else
31
+ # ...if it is not a rails project load configuration file
32
+ require 'config/config'
44
33
 
45
- require 'mainframe/customization/generic_functions'
46
- # puts "Extending Host class with #{Host3270::GenericFunctions}" if debug
47
- class ButlerMainframe::Host
48
- include Host3270::GenericFunctions
49
- end
34
+ # require the emulator sub class specified in the config.rb
35
+ raise "Define your host gateway in the configuration file!" unless ButlerMainframe.configuration.host_gateway
36
+ require "mainframe/emulators/#{ButlerMainframe.configuration.host_gateway.to_s.downcase}"
50
37
 
51
- if defined?(Host3270::CustomFunctions)
52
- # puts "Extending Host class with #{Host3270::CustomFunctions}" if debug
53
- class ButlerMainframe::Host
54
- include Host3270::CustomFunctions
38
+ %w(settings.yml private.yml).each do |file|
39
+ filepath = File.join(ButlerMainframe.root,'lib','config',file)
40
+ ButlerMainframe::Settings.load!(filepath, :env => ButlerMainframe.configuration.env) if File.exist? filepath
55
41
  end
56
- end
57
-
58
- =begin
59
- # To test in irb
60
- require 'butler-mainframe'
61
- host=ButlerMainframe::Host.new(debug: :full)
62
- host.scan_page
63
- host.navigate :next
64
- =end
42
+ end
data/lib/config/config.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  ButlerMainframe.configure do |config|
2
- config.host_gateway = :x3270
3
- config.session_path = '"C:/Program Files (x86)/wc3270/ws3270.exe" YOUR_HOST_IP -model 2 --'
4
- config.timeout = 6 # In seconds
2
+ # config.host_gateway = :x3270
3
+ # config.session_path = '"C:/Program Files (x86)/wc3270/ws3270.exe" YOUR_HOST_IP -model 2 --'
4
+ # config.timeout = 6 # In seconds
5
5
  end
6
6
 
@@ -4,5 +4,6 @@ ButlerMainframe.configure do |config|
4
4
  config.session_url = 'https://YOUR_HOST_IP/zephyr/Ecomes.zwh?sessionprofile=3270dsp/Sessions/host3270'
5
5
  config.session_tag = 1
6
6
  config.timeout = 6000
7
+ #config.env = 'production'
7
8
  end
8
9
 
@@ -7,5 +7,6 @@ ButlerMainframe.configure do |config|
7
7
  config.session_path = '"C:/Program Files (x86)/IBM/Personal Communications/pcsws.exe" "C:/Users/YOUR_USER/AppData/Roaming/IBM/Personal Communications/host3270.ws" /Q /H /S=A'
8
8
  config.session_tag = 'A'
9
9
  config.timeout = 6000
10
+ #config.env = 'production'
10
11
  end
11
12
 
@@ -2,5 +2,6 @@ ButlerMainframe.configure do |config|
2
2
  config.host_gateway = :x3270
3
3
  config.session_path = '"C:/Program Files (x86)/wc3270/ws3270.exe" YOUR_HOST_IP -model 2 --'
4
4
  config.timeout = 6 # In seconds
5
+ #config.env = 'production'
5
6
  end
6
7
 
@@ -2,7 +2,7 @@ module ButlerMainframe
2
2
  class Configuration
3
3
  attr_writer :allow_sign_up
4
4
 
5
- attr_accessor :language, :host_gateway, :browser_path, :session_url, :session_path, :session_tag, :timeout
5
+ attr_accessor :language, :host_gateway, :browser_path, :session_url, :session_path, :session_tag, :timeout, :env
6
6
 
7
7
  def initialize
8
8
  @language = :en
@@ -12,6 +12,7 @@ module ButlerMainframe
12
12
  @session_path = ""
13
13
  @session_tag = nil
14
14
  @timeout = 1000
15
+ @env = 'development'
15
16
  end
16
17
 
17
18
  end
@@ -12,12 +12,19 @@ module Butler
12
12
 
13
13
  def copy_to_local
14
14
  copy_file "butler/templates/custom_functions.rb", "config/initializers/butler_custom_functions.rb"
15
- copy_file "../config/settings.yml", "config/butler.yml"
15
+ copy_file "../config/settings.yml", "config/butler.yml"
16
+ copy_file "../config/private.yml", "config/butler_private.yml"
16
17
  file = "config/initializers/butler.rb"
17
18
  copy_file "../config/config_EXAMPLE_#{options[:emulator]}.rb", file
18
19
  append_file file do
19
20
  <<-FILE.gsub(/^ /, '')
20
- ButlerMainframe::Settings.load!(File.join(Rails.root,'config','butler.yml'), :env => Rails.env)
21
+ raise "Define your host gateway in the rails initializer file!" unless ButlerMainframe.configuration.host_gateway
22
+ require "mainframe/emulators/#{ButlerMainframe.configuration.host_gateway.to_s.downcase}"
23
+
24
+ %w(butler.yml butler_private.yml).each do |file|
25
+ filepath = File.join(Rails.root,'config',file)
26
+ ButlerMainframe::Settings.load!(filepath, :env => Rails.env) if File.exist? filepath
27
+ end
21
28
  FILE
22
29
  end
23
30
  end
@@ -1,27 +1,16 @@
1
1
  # These modules contain extensions for the Host class
2
- module Host3270
2
+ module ButlerMainframe
3
3
  module CustomFunctions
4
4
  ### Insert here your custom methods ###
5
5
 
6
6
  ### Update default generic function ###
7
- # def do_enter; exec_command "ENTER" end
8
- #
9
- # def go_back; exec_command "PA2" end
10
- #
11
- # def do_confirm; exec_command "PF3" end
12
- #
13
- # def do_quit; exec_command "CLEAR" end
14
- #
15
- # def do_erase; exec_command "ERASE EOF" end
16
- #
17
- # # If you add your static screen you must add it in the navigation method to define how to manage it
7
+ # If you add your static screen you must add it in the navigation method to define how to manage it
18
8
  # def destination_list
19
- # [
20
- # :company_menu,
21
- # :cics_selection,
22
- # :session_login,
23
- # :next,
24
- # :back]
9
+ # [:company_menu,
10
+ # :cics_selection,
11
+ # :session_login,
12
+ # :next,
13
+ # :back]
25
14
  # end
26
15
  #
27
16
  # # Use navigation method to move through the static screens
@@ -32,91 +21,98 @@ module Host3270
32
21
  # # :raise_on_abend => false raise an exception if an abend is occured
33
22
  # def navigate destination, options={}
34
23
  # options = {
24
+ # :session_user => ButlerMainframe::Settings.session_user,
25
+ # :session_password => ButlerMainframe::Settings.session_password,
35
26
  # :cics => ButlerMainframe::Settings.cics,
36
- # :user => ButlerMainframe::Settings.user,
37
- # :password => ButlerMainframe::Settings.password,
27
+ # :company_menu => ButlerMainframe::Settings.company_menu,
38
28
  # :raise_on_abend => false
39
29
  # }.merge(options)
40
- # attempts_number = ButlerMainframe::Settings.navigation_iterations
30
+ # max_attempts_number = ButlerMainframe::Settings.max_attempts_number
41
31
  # transactions_cics = ButlerMainframe::Settings.transactions_cics
42
32
  #
43
33
  # raise "Destination #{destination} not valid, please use: #{destination_list.join(', ')}" unless destination_list.include? destination
44
- # bol_found = nil
45
- # attempts_number.times do
34
+ #
35
+ # puts "Navigating to #{destination}" if @debug
36
+ # destination_found = nil
37
+ # attempt_number = 0
38
+ # while !destination_found do
39
+ # attempt_number += 1
40
+ #
46
41
  # if abend?
42
+ # puts "Navigate: abend" if @debug
47
43
  # options[:raise_on_abend] ? raise(catch_abend) : do_quit
48
44
  # elsif company_menu?
45
+ # puts "Navigating to #{destination} from company menu" if @debug
49
46
  # case destination
50
47
  # when :cics_selection,
51
48
  # :session_login then
52
49
  # do_quit
53
50
  # when :back then
54
51
  # do_quit
55
- # bol_found = true; break
52
+ # destination_found = true
56
53
  # when :next then
57
- # company_menu
58
- # bol_found = true; break
59
- # when :company_menu then bol_found = true; break
54
+ # company_menu options[:company_menu]
55
+ # destination_found = true
56
+ # when :company_menu then destination_found = true
60
57
  # else
61
58
  # # Every other destination is forward
62
- # company_menu
59
+ # company_menu options[:company_menu]
63
60
  # end
64
61
  # elsif cics?
62
+ # puts "Navigating to #{destination} from cics" if @debug
65
63
  # case destination
66
64
  # when :cics_selection,
67
65
  # :session_login then
68
- # write ButlerMainframe::Settings.logoff_cics, :y => 1, :x => 1
69
- # do_enter
66
+ # execute_cics ButlerMainframe::Settings.logoff_cics
70
67
  # when :back then
71
- # write ButlerMainframe::Settings.logoff_cics, :y => 1, :x => 1
72
- # do_enter
73
- # bol_found = true; break
68
+ # execute_cics ButlerMainframe::Settings.logoff_cics
69
+ # destination_found = true
74
70
  # when :next then
75
- # write transactions_cics[:main_application], :y => 1, :x => 1
76
- # do_enter
77
- # bol_found = true; break
71
+ # execute_cics transactions_cics[:main_application]
72
+ # destination_found = true
78
73
  # when :company_menu then
79
- # write transactions_cics[:company_menu], :y => 1, :x => 1
80
- # do_enter
74
+ # execute_cics transactions_cics[:company_menu]
81
75
  # else
82
76
  # #If we are in CICS with blank screen start the first transaction
83
- # write transactions_cics[:main_application], :y => 1, :x => 1
84
- # do_enter
77
+ # execute_cics transactions_cics[:main_application]
85
78
  # end
86
79
  # elsif cics_selection?
80
+ # puts "Navigating to #{destination} from cics selection" if @debug
87
81
  # case destination
88
- # when :cics_selection then bol_found = true; break
82
+ # when :cics_selection then destination_found = true
89
83
  # when :session_login then exec_command("PF3")
90
84
  # when :next then
91
85
  # cics_selection options[:cics] if options[:cics]
92
- # bol_found = true; break
86
+ # destination_found = true
93
87
  # when :back then
94
88
  # exec_command("PF3")
95
- # bol_found = true; break
89
+ # destination_found = true
96
90
  # else
97
91
  # cics_selection options[:cics] if options[:cics]
98
92
  # end
99
93
  # elsif session_login?
94
+ # puts "Navigating to #{destination} from session login" if @debug
100
95
  # case destination
101
96
  # when :session_login,
102
- # :back then bol_found = true; break
97
+ # :back then destination_found = true
103
98
  # when :next then
104
- # session_login options[:user], options[:password] if options[:user] && options[:password]
105
- # bol_found = true; break
99
+ # session_login options[:session_user], options[:session_password]
100
+ # destination_found = true
106
101
  # else
107
- # session_login options[:user], options[:password] if options[:user] && options[:password]
102
+ # session_login options[:session_user], options[:session_password]
108
103
  # end
109
104
  # else
105
+ # puts "Navigating to #{destination} from unknown screen" if @debug
110
106
  # # If we do not know where we are...
111
107
  # case destination
112
- # when :session_login then
108
+ # when :session_login then
113
109
  # # ...to come back to the first screen we surely have to go back
114
110
  # go_back
115
111
  # when :back then
116
112
  # # ...we can try to go back (not all the screen may go back in the same way)
117
113
  # go_back
118
- # bol_found = true; break
119
- # when :next then
114
+ # destination_found = true
115
+ # when :next then
120
116
  # # ...but we dont know how to move forward
121
117
  # raise "Define how to go forward in the navigation method on generic function module"
122
118
  # else
@@ -124,10 +120,11 @@ module Host3270
124
120
  # raise "Destination #{destination} not defined in the current screen"
125
121
  # end
126
122
  # end
123
+ # break if attempt_number > max_attempts_number
127
124
  # wait_session
128
125
  # end
129
126
  #
130
- # raise "It was waiting #{destination} map instead of: #{screen_title(:rows => 2).strip}" unless bol_found
127
+ # raise "It was waiting #{destination} map instead of: #{screen_title(:rows => 2).strip}" unless destination_found
131
128
  # end
132
129
  #
133
130
  # # Check if we are the first blank cics screen
@@ -141,15 +138,20 @@ module Host3270
141
138
  # end
142
139
  #
143
140
  # # Login to mainframe
144
- # # param1 user
145
- # # param2 password [sensible data]
146
- # def session_login user, password
141
+ # # param1 user(array) [text, y, x]
142
+ # # param2 password(array) [text, y, x]
143
+ # def session_login ar_user, ar_password
147
144
  # puts "Starting session login..." if @debug
145
+ # user, y_user, x_user = ar_user
146
+ # raise "Check session user configuration! #{user} #{y_user} #{x_user}" unless user && y_user && x_user
147
+ # password, y_password, x_password = ar_password
148
+ # raise "Check session password configuration! #{password} #{y_password} #{x_password}" unless password && y_password && x_password
149
+ #
148
150
  # wait_session
149
151
  # #inizializza_sessione
150
152
  # raise "It was waiting session login map instead of: #{screen_title}" unless session_login?
151
- # write user, :y => 16, :x => 36
152
- # write password, :y => 17, :x => 36, :sensible_data => true
153
+ # write user, :y => y_user, :x => x_user
154
+ # write password, :y => y_password, :x => x_password, :sensible_data => true
153
155
  # do_enter
154
156
  # end
155
157
  #
@@ -159,12 +161,15 @@ module Host3270
159
161
  # end
160
162
  #
161
163
  # # On this map, we have to select the cics environment
162
- # # param1 cics usually is a number
163
- # def cics_selection cics
164
+ # # param1 cics(array) [text, y, x]
165
+ # def cics_selection ar_cics
164
166
  # puts "Starting selezione_cics..." if @debug
167
+ # cics, y_cics, x_cics = ar_cics
168
+ # raise "Check cics configuration! #{cics} #{y_cics} #{x_cics}" unless cics && y_cics && x_cics
169
+ #
165
170
  # wait_session
166
171
  # raise "It was waiting cics selezion map instead of: #{screen_title}, message: #{catch_message}" unless cics_selection?
167
- # write cics, :y => 23, :x => 14
172
+ # write cics, :y => y_cics, :x => x_cics
168
173
  # do_enter
169
174
  # wait_session 1
170
175
  # end
@@ -176,11 +181,14 @@ module Host3270
176
181
  #
177
182
  # # On this map, we have to select the cics environment
178
183
  # # param1 cics usually is a number
179
- # def company_menu
184
+ # def company_menu ar_menu
180
185
  # puts "Starting company menu..." if @debug
186
+ # menu, y_menu, x_menu = ar_menu
187
+ # raise "Check company menu configuration! #{menu} #{y_menu} #{x_menu}" unless menu && y_menu && x_menu
188
+ #
181
189
  # wait_session
182
190
  # raise "It was waiting company menu map instead of: #{screen_title}, message: #{catch_message}" unless company_menu?
183
- # write "01", :y => 24, :x => 43
191
+ # write menu, :y => y_menu, :x => x_menu
184
192
  # do_enter
185
193
  # end
186
194
  #
@@ -214,9 +222,24 @@ module Host3270
214
222
  # }.merge(options)
215
223
  # scan(:y1 => 1, :x1 => 1, :y2 => options[:rows], :x2 => 80)
216
224
  # end
225
+ #
226
+ # def execute_cics name
227
+ # write name, :y => 1, :x => 2
228
+ # do_enter
229
+ # end
230
+ #
231
+ # def do_enter; exec_command "ENTER" end
232
+ #
233
+ # def go_back; exec_command "PA2" end
234
+ #
235
+ # def do_confirm; exec_command "PF3" end
236
+ #
237
+ # def do_quit; exec_command "CLEAR" end
238
+ #
239
+ # def do_erase; exec_command "ERASE EOF" end
217
240
  end
218
241
  end
219
242
 
220
243
  class ButlerMainframe::Host
221
- include Host3270::CustomFunctions
244
+ include ButlerMainframe::CustomFunctions
222
245
  end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ rails generate butler_helper Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,5 @@
1
+ class Rails::ButlerMainframeTestGenerator < Rails::Generators::NamedBase
2
+ source_root File.expand_path('../templates', __FILE__)
3
+
4
+ hook_for :test_framework
5
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ rails generate butler_helper Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,46 @@
1
+ require 'rails/generators/test_unit'
2
+ require 'rails/generators/resource_helpers'
3
+
4
+ module TestUnit # :nodoc:
5
+ module Generators # :nodoc:
6
+ class ButlerMainframeTestGenerator < Base # :nodoc:
7
+ include Rails::Generators::ResourceHelpers
8
+
9
+ source_root File.expand_path('../templates', __FILE__)
10
+
11
+ def create_test_file
12
+ create_file "test/#{/^4\./ === Rails.version ? 'models' : 'unit'}/butler_mainframe_#{file_name}_test.rb",
13
+ <<-FILE.gsub(/^ /, '')
14
+ require 'test_helper'
15
+
16
+ class #{class_name}Test < ActiveSupport::TestCase
17
+ test "Basic navigation" do
18
+ params = {:debug => true, :wait_debug => 0.5}
19
+ host = ButlerMainframe::Host.new(params)
20
+ host.navigate :session_login
21
+ assert host.session_login?, 'navigate :session_login => this is not the session login'
22
+
23
+ host.navigate :next
24
+ assert !host.session_login?, 'navigate :next => does not pass login screen'
25
+
26
+ host.close_session
27
+ assert host.action[:object] == nil, "Close session failed!"
28
+ end
29
+
30
+ test "#{class_name} navigation" do
31
+ params = {:debug => true, :wait_debug => 0.5}
32
+ host = ButlerMainframe::Host.new(params)
33
+
34
+ #host.navigate :your_starting_screen
35
+ # WRITE YOUR TEST
36
+
37
+ host.close_session
38
+ assert host.action[:object] == nil, "Close session failed!"
39
+ end
40
+ end
41
+ FILE
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -1,5 +1,5 @@
1
1
  # These modules contain extensions for the Host class
2
- module Host3270
2
+ module ButlerMainframe
3
3
  # This module can be use on rails project.
4
4
  #
5
5
  # Create a polimorphic model:
@@ -1,25 +1,14 @@
1
1
  # These modules contain extensions for the Host class
2
- module Host3270
2
+ module ButlerMainframe
3
3
  module GenericFunctions
4
4
 
5
- def do_enter; exec_command "ENTER" end
6
-
7
- def go_back; exec_command "PA2" end
8
-
9
- def do_confirm; exec_command "PF3" end
10
-
11
- def do_quit; exec_command "CLEAR" end
12
-
13
- def do_erase; exec_command "ERASE EOF" end
14
-
15
5
  # If you add your static screen you must add it in the navigation method to define how to manage it
16
6
  def destination_list
17
- [
18
- :company_menu,
19
- :cics_selection,
20
- :session_login,
21
- :next,
22
- :back]
7
+ [:company_menu,
8
+ :cics_selection,
9
+ :session_login,
10
+ :next,
11
+ :back]
23
12
  end
24
13
 
25
14
  # Use navigation method to move through the static screens
@@ -236,6 +225,17 @@ module Host3270
236
225
  write name, :y => 1, :x => 2
237
226
  do_enter
238
227
  end
228
+
229
+ def do_enter; exec_command "ENTER" end
230
+
231
+ def go_back; exec_command "PA2" end
232
+
233
+ def do_confirm; exec_command "PF3" end
234
+
235
+ def do_quit; exec_command "CLEAR" end
236
+
237
+ def do_erase; exec_command "ERASE EOF" end
238
+
239
239
  end
240
240
 
241
241
  end
@@ -1,5 +1,4 @@
1
1
  require 'win32ole'
2
- require 'mainframe/host_base'
3
2
 
4
3
  # This class use Rocket 3270 emulator API
5
4
  # http://www.zephyrcorp.com/legacy-integration/Documentation/passport_host_integration_objects.htm
@@ -12,37 +11,37 @@ module ButlerMainframe
12
11
  def sub_create_object options={}
13
12
  str_obj = 'PASSPORT.System'
14
13
  puts "#{Time.now.strftime "%H:%M:%S"} Creating object #{str_obj}..." if @debug == :full
15
- @action[:ole] = WIN32OLE.new(str_obj)
16
- @screen = @action[:ole].Sessions(@session_tag).Screen if sub_object_created?
14
+ @action[:object] = WIN32OLE.new(str_obj)
15
+ @screen = @action[:object].Sessions(@session_tag).Screen if sub_object_created?
17
16
  end
18
17
 
19
18
  # Check is session is started
20
19
  def sub_object_created?
21
- res = @action[:ole] && @action[:ole].Sessions(@session_tag)
20
+ res = @action[:object] && @action[:object].Sessions(@session_tag)
22
21
  puts "#{Time.now.strftime "%H:%M:%S"} Terminal successfully detected" if @debug == :full && res
23
22
  res
24
23
  end
25
24
 
26
25
  # Check is session is operative
27
26
  def sub_object_ready?
28
- res = @action[:ole].Sessions(@session_tag).Connected == -1
27
+ res = @action[:object].Sessions(@session_tag).Connected == -1
29
28
  puts "#{Time.now.strftime "%H:%M:%S"} Session ready" if @debug == :full && res
30
29
  res
31
30
  end
32
31
 
33
32
  def sub_name
34
- "#{@action[:ole].Name} #{@action[:ole].Sessions(@session_tag).Name}"
33
+ "#{@action[:object].Name} #{@action[:object].Sessions(@session_tag).Name}"
35
34
  end
36
35
 
37
36
  def sub_fullname
38
- "#{sub_name} #{@action[:ole].Sessions(@session_tag).FullName}"
37
+ "#{sub_name} #{@action[:object].Sessions(@session_tag).FullName}"
39
38
  end
40
39
 
41
40
  #Ends the connection and closes the session
42
41
  def sub_close_session
43
- @action[:ole].Sessions(@session_tag).Close
44
- @action[:ole].Quit
45
- @action[:ole] = nil
42
+ @action[:object].Sessions(@session_tag).Close
43
+ @action[:object].Quit
44
+ @action[:object] = nil
46
45
  end
47
46
 
48
47
  #Execute keyboard command like PF1 or PA2 or ENTER ...
@@ -1,5 +1,4 @@
1
1
  require 'win32ole'
2
- require 'mainframe/host_base'
3
2
 
4
3
  # This class use IBM personal communication
5
4
  # http://www-01.ibm.com/support/knowledgecenter/SSEQ5Y_6.0.0/welcome.html
@@ -14,38 +13,38 @@ module ButlerMainframe
14
13
  def sub_create_object options={}
15
14
  str_obj = 'PComm.autECLSession'
16
15
  puts "#{Time.now.strftime "%H:%M:%S"} Creating object #{str_obj}..." if @debug == :full
17
- @action[:ole] = WIN32OLE.new(str_obj)
18
- @action[:ole].SetConnectionByName @session_tag
19
- @space = @action[:ole].autECLPS
20
- @screen = @action[:ole].autECLOIA
16
+ @action[:object] = WIN32OLE.new(str_obj)
17
+ @action[:object].SetConnectionByName @session_tag
18
+ @space = @action[:object].autECLPS
19
+ @screen = @action[:object].autECLOIA
21
20
  end
22
21
 
23
22
  # Check is session is started
24
23
  def sub_object_created?
25
- res = @action[:ole] && @action[:ole].CommStarted
24
+ res = @action[:object] && @action[:object].CommStarted
26
25
  puts "#{Time.now.strftime "%H:%M:%S"} Terminal successfully detected" if @debug == :full && res
27
26
  res
28
27
  end
29
28
 
30
29
  # Check is session is operative
31
30
  def sub_object_ready?
32
- res = @action[:ole].Ready
31
+ res = @action[:object].Ready
33
32
  puts "#{Time.now.strftime "%H:%M:%S"} Session ready" if @debug == :full && res
34
33
  res
35
34
  end
36
35
 
37
36
  def sub_name
38
- "PComm #{@action[:ole].Name}"
37
+ "PComm #{@action[:object].Name}"
39
38
  end
40
39
 
41
40
  def sub_fullname
42
- "#{sub_name} #{@action[:ole].ConnType}"
41
+ "#{sub_name} #{@action[:object].ConnType}"
43
42
  end
44
43
 
45
44
  #Ends the connection and closes the session
46
45
  def sub_close_session
47
- @action[:ole].StopCommunication
48
- @action[:ole] = nil
46
+ @action[:object].StopCommunication
47
+ @action[:object] = nil
49
48
  # See http://www-01.ibm.com/support/knowledgecenter/SSEQ5Y_6.0.0/com.ibm.pcomm.doc/books/html/admin_guide10.htm?lang=en
50
49
  Process.spawn "PCOMSTOP /S=#{@session_tag} /q" if @pid
51
50
  # Process.kill 9, @pid #Another way is to kill the process but the session start 2nd process pcscm.exe
@@ -1,5 +1,4 @@
1
1
  require 'open3'
2
- require 'mainframe/host_base'
3
2
 
4
3
  # This class use X3270, an interesting project open source
5
4
  # http://x3270.bgp.nu/Windows/wc3270-script.html
@@ -14,6 +13,7 @@ module ButlerMainframe
14
13
  puts "#{Time.now.strftime "%H:%M:%S"} Creating object #{str_obj}..." if @debug == :full
15
14
  @action = {}
16
15
  @action[:in], @action[:out], @action[:thr] = Open3.popen2e(str_obj)
16
+ @action[:object] = true
17
17
  sleep WAIT_AFTER_START_SESSION
18
18
  @pid = @action[:thr].pid
19
19
  end
@@ -44,6 +44,7 @@ module ButlerMainframe
44
44
  def sub_close_session
45
45
  @action[:in].close
46
46
  @action[:out].close
47
+ @action[:object] = nil
47
48
  end
48
49
 
49
50
  #Execute keyboard command like PF1 or PA2 or ENTER ...
@@ -1,7 +1,10 @@
1
+ require 'mainframe/customization/generic_functions'
2
+
1
3
  module ButlerMainframe
2
4
  # This is the host class base that contains high level logic
3
5
  # It uses sub method that have to be defined in the specific sub class
4
6
  class HostBase
7
+ include ButlerMainframe::GenericFunctions
5
8
 
6
9
  attr_reader :action, :wait
7
10
  attr_accessor :debug
@@ -40,6 +43,10 @@ module ButlerMainframe
40
43
 
41
44
  # Ends the connection and closes the session
42
45
  def close_session
46
+ # puts "[DEPRECATED] .close_session will no longer be available, please use .quit"
47
+ quit
48
+ end
49
+ def quit
43
50
  puts "Closing session with criterion \"#{@close_session}\"" if @debug
44
51
  case @close_session
45
52
  when :always
@@ -57,6 +64,7 @@ module ButlerMainframe
57
64
  end
58
65
  end
59
66
 
67
+
60
68
  # Sleep time between operations
61
69
  def wait_session wait=nil
62
70
  sleep(wait || (@debug ? @wait_debug : @wait))
data/test/test.rake CHANGED
@@ -43,27 +43,31 @@ def simple_iteration options={}
43
43
  host = options[:host] || ButlerMainframe::Host.new(params)
44
44
 
45
45
  navigate host, :session_login
46
-
47
46
  str_screen1 = host.scan_page
48
47
  raise 'host.scan_page' if str_screen1.empty?
48
+ raise 'navigate :session_login => this is not the session login' unless host.session_login?
49
49
 
50
50
  navigate host, :next
51
51
  str_screen2 = host.scan_page
52
- raise 'navigate :next does not pass login screen' if str_screen1 == str_screen2
52
+ raise 'navigate :next from :session_login => the screen is not changed' if str_screen1 == str_screen2
53
+
54
+ raise 'navigate :next => does not pass login screen' if host.session_login?
53
55
 
54
56
  navigate host, :next
55
- str_screen2 = host.scan_page
56
- raise 'navigate :next does not pass cics selection' if str_screen1 == str_screen2
57
+ raise 'navigate :next => does not pass cics selection' if host.cics_selection?
57
58
 
58
59
  # Go back until the first screen
59
60
  navigate host, :session_login
61
+ raise 'navigate :session_login => this is not the session login' unless host.session_login?
60
62
 
61
- raise "host.scan row failed" unless host.scan(:y => 1, :x => 1, :len => 80).size == 80
62
- raise "host.scan area failed" unless host.scan(:y1 => 1, :x1 => 1, :y2 => 3, :x2 => 80).size == 240
63
+ raise "host.scan row failed" unless host.scan(:y => 1, :x => 1, :len => ButlerMainframe::Host::MAX_TERMINAL_COLUMNS).size == ButlerMainframe::Host::MAX_TERMINAL_COLUMNS
64
+ raise "host.scan area failed" unless host.scan(:y1 => 1, :x1 => 1, :y2 => 3, :x2 => ButlerMainframe::Host::MAX_TERMINAL_COLUMNS).size == (ButlerMainframe::Host::MAX_TERMINAL_COLUMNS * 3)
63
65
 
64
66
  navigate host, :back
67
+ raise 'navigate :back from :session_login => this is not the session login' unless host.session_login?
65
68
 
66
69
  navigate host, :company_menu
70
+ raise 'navigate :company_menu from :session_login => this is not the company menu' unless host.company_menu?
67
71
 
68
72
  navigate host, :next
69
73
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: butler-mainframe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marco Mastrodonato
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-26 00:00:00.000000000 Z
11
+ date: 2015-10-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: This gem provides a virtual butler which can perform your custom tasks
14
14
  on a 3270 emulator. Choose your emulator, configure your task and discover a new
@@ -30,13 +30,16 @@ files:
30
30
  - lib/config/config_EXAMPLE_x3270.rb
31
31
  - lib/config/private.yml
32
32
  - lib/config/settings.yml
33
- - lib/config/settings_EXAMPLE.yml
34
33
  - lib/core/configuration.rb
35
34
  - lib/core/configuration_dynamic.rb
36
35
  - lib/generators/butler/USAGE
37
36
  - lib/generators/butler/install_generator.rb
38
37
  - lib/generators/butler/templates/custom_functions.rb
39
38
  - lib/generators/butler_mainframe.rb
39
+ - lib/generators/rails/butler_mainframe_test/USAGE
40
+ - lib/generators/rails/butler_mainframe_test/butler_mainframe_test_generator.rb
41
+ - lib/generators/test_unit/butler_mainframe_test/USAGE
42
+ - lib/generators/test_unit/butler_mainframe_test/butler_mainframe_test_generator.rb
40
43
  - lib/mainframe/customization/active_record.rb
41
44
  - lib/mainframe/customization/generic_functions.rb
42
45
  - lib/mainframe/emulators/passport.rb
@@ -1,25 +0,0 @@
1
- defaults: &defaults
2
- # The max number of iteration through static screen
3
- max_attempts_number: 20
4
- session_login_tag: 'EMSP00' # Use a regular expression
5
- cics_selection_tag: 'EMSP01' # Use a regular expression
6
- cics: ['7', 23, 14] # Text to write at coordinates y, x
7
- company_menu: ['01', 24, 43]
8
- logoff_cics: 'cesf logoff'
9
- company_menu_tag: '\*\* \*\* \*\* \*\*' # Use a regular expression
10
- # Starts these transactions from blank cics in order to move forward
11
- transactions_cics:
12
- company_menu: 'vita'
13
- main_application: 'life'
14
- #foo: add every variable you need and use it with => ButlerMainframe::Settings.foo
15
- # bar: sub variable are accessible with hash => ButlerMainframe::Settings.foo[:bar]
16
-
17
- development:
18
- <<: *defaults
19
-
20
- test:
21
- <<: *defaults
22
-
23
- production:
24
- <<: *defaults
25
- cics: ['4', 23, 14]