butler-mainframe 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +46 -23
- data/lib/config/config.rb +1 -1
- data/lib/config/config_EXAMPLE_passport.rb +1 -1
- data/lib/config/config_EXAMPLE_pcomm.rb +1 -1
- data/lib/config/config_EXAMPLE_x3270.rb +1 -1
- data/lib/config/settings.yml +15 -6
- data/lib/config/settings_EXAMPLE.yml +15 -6
- data/lib/generators/butler/templates/custom_functions.rb +77 -16
- data/lib/mainframe/customization/generic_functions.rb +87 -20
- data/lib/mainframe/emulators/passport.rb +9 -9
- data/lib/mainframe/emulators/pcomm.rb +14 -11
- data/lib/mainframe/emulators/x3270.rb +7 -7
- data/lib/mainframe/host_base.rb +55 -27
- data/test/test.rake +93 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54a4d86d300e73b9a93e3877cb23884911c51bd3
|
4
|
+
data.tar.gz: 4eb90e449628bca9f88f45f7b06038296ea86ff0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da00ccbc5269ee7cf04bf3cf3cd396b919e31da9456d1bfd13103b2942cdd7bf50158a574e4880e217b8030df5f96e491de4d5389de23cb509290b7c1f139fa2
|
7
|
+
data.tar.gz: 8ab5b447a48c02abb919ea0d82294b44be93685845f51a967a95aaa7d18821feb93e10fff80ff7362a8a5d0e73d6eeb88cb6eae50d0dcfe72197c42dd529caf2
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
0.3.0 [☰](https://github.com/marcomd/butler-mainframe/compare/v0.2.0...v0.3.0) October 22th, 2015
|
2
|
+
------------------------------
|
3
|
+
* Improved the host base class code to make it simpler
|
4
|
+
* Improved automated tests with a more complex sequence and three iterations with decreasing latencies
|
5
|
+
* Pcomm sub class now use safer method to close session
|
6
|
+
* x3270 sub class is now more stable, It now passes all the tests although not always, rarely this does not happen with short delay time. There is still something to fix.
|
7
|
+
* Improved navigation and added new setting parameters
|
8
|
+
* Improved documentation
|
9
|
+
* Several little improvements
|
10
|
+
|
1
11
|
0.2.0 [☰](https://github.com/marcomd/butler-mainframe/compare/v0.1.0...v0.2.0) October 20th, 2015
|
2
12
|
------------------------------
|
3
13
|
* Added support for the free and open source x3270 terminal emulator, use :x3270 as host gateway in butler configuration
|
data/README.md
CHANGED
@@ -26,7 +26,7 @@ At the moment are managed the below emulators. First two are commercial which mu
|
|
26
26
|
|
27
27
|
* [Passport web to host by Rocket Software](http://www.rocketsoftware.com/resource/rocket-passport-web-host-overview)
|
28
28
|
* [Personal communication by IBM](http://www-03.ibm.com/software/products/en/pcomm)
|
29
|
-
* [x3270 maintained by Paul Mates](http://x3270.bgp.nu/)
|
29
|
+
* [x3270 maintained by Paul Mates](http://x3270.bgp.nu/) (only on ruby 1.9+)
|
30
30
|
|
31
31
|
|
32
32
|
## Configuration
|
@@ -40,9 +40,9 @@ In the config folder there are two files:
|
|
40
40
|
|
41
41
|
config.rb can be used for the configuration of the gem and the emulator
|
42
42
|
|
43
|
-
|
44
|
-
# Example to configure Passport web to host
|
43
|
+
Example to configure Passport web to host:
|
45
44
|
|
45
|
+
```ruby
|
46
46
|
ButlerMainframe.configure do |config|
|
47
47
|
config.host_gateway = :passport
|
48
48
|
config.browser_path = 'c:/Program Files (x86)/Internet Explorer/iexplore.exe'
|
@@ -52,9 +52,9 @@ ButlerMainframe.configure do |config|
|
|
52
52
|
end
|
53
53
|
```
|
54
54
|
|
55
|
-
|
56
|
-
# Example to configure Personal communication
|
55
|
+
Example to configure Personal communication:
|
57
56
|
|
57
|
+
```ruby
|
58
58
|
ButlerMainframe.configure do |config|
|
59
59
|
config.host_gateway = :pcomm
|
60
60
|
config.session_path = '"C:/Program Files (x86)/IBM/Personal Communications/pcsws.exe" "C:/Users/Marco/AppData/Roaming/IBM/Personal Communications/host3270.ws"'
|
@@ -63,8 +63,9 @@ ButlerMainframe.configure do |config|
|
|
63
63
|
end
|
64
64
|
```
|
65
65
|
|
66
|
+
Example to configure X3270:
|
67
|
+
|
66
68
|
```ruby
|
67
|
-
# Example to configure X3270
|
68
69
|
ButlerMainframe.configure do |config|
|
69
70
|
config.host_gateway = :x3270
|
70
71
|
config.session_path = '"C:/Program Files (x86)/wc3270/ws3270.exe" 127.0.0.1 -model 2 --'
|
@@ -171,42 +172,58 @@ run generator to copy configuration files suitable for the emulator you need
|
|
171
172
|
|
172
173
|
rails g butler:install --emulator=passport
|
173
174
|
|
175
|
+
You should have a model for every function to perform.
|
176
|
+
In this simple example i have to insert an invoice number on a cics map so i create the invoice model:
|
177
|
+
|
178
|
+
rails generate scaffold invoice number:integer
|
179
|
+
|
180
|
+
You may create a polimorphic model to save mainframe screen:
|
181
|
+
|
182
|
+
rails generate migration CreateScreens hook_id:integer 'hook_type:string{30}' 'screen_type:integer{1}' video:text 'message:string{160}' 'cursor_x:integer{1}' 'cursor_y:integer{1}'
|
183
|
+
|
184
|
+
Create something like this:
|
185
|
+
|
174
186
|
```ruby
|
175
187
|
Class Invoice
|
176
|
-
|
188
|
+
has_many :screens, :as => :hook, :dependent => :destroy
|
189
|
+
|
190
|
+
# ... your rails code: validations, scopes etc.
|
177
191
|
|
192
|
+
# Your main function method that perform the action on the mainframe
|
178
193
|
def host3270
|
179
194
|
@host = ButlerMainframe::Host.new
|
195
|
+
|
196
|
+
# Move to your starting position
|
197
|
+
# They often are static screens so it's easier to use navigate method
|
180
198
|
@host.navigate :my_starting_position
|
181
199
|
|
182
200
|
# Always check whether we are positioned on the screen that we expect
|
183
|
-
raise 'Screen not expected' unless
|
201
|
+
raise 'Screen not expected' unless @host.my_function_start_screen?
|
184
202
|
|
185
203
|
# We develop the function.
|
186
|
-
# In this simple case we put a number in a map
|
187
|
-
|
204
|
+
# In this simple case we put a number in a map CICS at row 10 and column 5
|
205
|
+
# as option we also choose to erase any previous value in the field
|
206
|
+
@host.write self.number, y: 10, x: 5, erase_field_first: true
|
207
|
+
|
208
|
+
# Press enter because the example mainframe program expects it as confirmation
|
188
209
|
@host.do_enter
|
189
210
|
|
190
|
-
#
|
191
|
-
raise 'Message not expected' unless /SUCCESSFUL/ ===
|
211
|
+
# Read the confirmation message otherwise raise an exception
|
212
|
+
raise 'Message not expected' unless /SUCCESSFUL/ === @host.catch_message
|
192
213
|
|
214
|
+
# At the end close the session
|
193
215
|
@host.close_session
|
194
216
|
rescue
|
195
|
-
|
217
|
+
# Save the screen as error to show to your mainframe users
|
218
|
+
@host.screenshot :error
|
196
219
|
# Manage the invoice status etc.
|
197
220
|
end
|
198
221
|
end
|
199
222
|
```
|
200
223
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
In the model to be related to screen we insert:
|
206
|
-
|
207
|
-
```ruby
|
208
|
-
has_many :screens, :as => :hook, :dependent => :destroy
|
209
|
-
```
|
224
|
+
Massive uses or one shot depends on your needs.
|
225
|
+
The uses are many and only limited by your imagination!
|
226
|
+
Experiment and you'll find the solution right for you :rocket:
|
210
227
|
|
211
228
|
|
212
229
|
## Test with rake
|
@@ -220,6 +237,10 @@ For more informations:
|
|
220
237
|
|
221
238
|
bundle exec rake -T
|
222
239
|
|
240
|
+
These tests consist in iterations of a simple navigation sequence.
|
241
|
+
Each iteration uses different latency times, we start from high and therefore simple for the emulator to the default very low.
|
242
|
+
It is not so easy make more complex sequence to share because mainframe screens are strongly diversified but everyone can add their own and iterate as many times as deemed appropriate.
|
243
|
+
|
223
244
|
|
224
245
|
## More informations about supported emulators
|
225
246
|
|
@@ -336,7 +357,9 @@ session.autECLOIA.ole_methods (screen):
|
|
336
357
|
### x3270
|
337
358
|
|
338
359
|
Documentation can be found [here](http://x3270.bgp.nu/documentation-manpages.html)
|
360
|
+
|
339
361
|
__At the moment it doesn't support check on protect area__
|
362
|
+
|
340
363
|
__x3270 module works only on ruby 1.9+__
|
341
364
|
|
342
365
|
```ruby
|
@@ -348,7 +371,7 @@ Read the methods list documentation: [windows](http://x3270.bgp.nu/Windows/wc327
|
|
348
371
|
|
349
372
|
## ToDo
|
350
373
|
|
351
|
-
* Improve unit test
|
374
|
+
* <s>Improve unit test</s> **Done** although it is still a simple rake
|
352
375
|
* Improve static navigation
|
353
376
|
* Add meta class to choose your host method name and multi language support as well
|
354
377
|
|
data/lib/config/config.rb
CHANGED
@@ -3,6 +3,6 @@ ButlerMainframe.configure do |config|
|
|
3
3
|
config.browser_path = 'c:/Program Files (x86)/Internet Explorer/iexplore.exe'
|
4
4
|
config.session_url = 'https://localhost/zephyr/Ecomes.zwh?sessionprofile=3270dsp/Sessions/host3270'
|
5
5
|
config.session_tag = 1
|
6
|
-
config.timeout =
|
6
|
+
config.timeout = 6000
|
7
7
|
end
|
8
8
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
ButlerMainframe.configure do |config|
|
2
2
|
config.host_gateway = :pcomm
|
3
|
-
config.session_path = '"C:/Program Files (x86)/IBM/Personal Communications/pcsws.exe" "C:/Users/XXXXXXXXXX/AppData/Roaming/IBM/Personal Communications/host3270.ws"'
|
3
|
+
config.session_path = '"C:/Program Files (x86)/IBM/Personal Communications/pcsws.exe" "C:/Users/XXXXXXXXXX/AppData/Roaming/IBM/Personal Communications/host3270.ws" /Q /H /S=A'
|
4
4
|
config.session_tag = 'A'
|
5
5
|
config.timeout = 6000
|
6
6
|
end
|
data/lib/config/settings.yml
CHANGED
@@ -1,10 +1,19 @@
|
|
1
1
|
defaults: &defaults
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
# The number of iteration through static screen
|
3
|
+
navigation_iterations: 10
|
4
|
+
cics: '7'
|
5
|
+
user: 'YOURUSER'
|
6
|
+
password: 'YOURPASSWORD'
|
7
|
+
#foo: add every variable you need and use it with => ButlerMainframe::Settings.foo
|
8
|
+
# bar: sub variable are accessible with hash => ButlerMainframe::Settings.foo[:bar]
|
9
|
+
logoff_cics: 'cesf logoff'
|
10
|
+
session_login_tag: 'EMSP00' #use a regular expression
|
11
|
+
cics_selection_tag: 'EMSP01' #use a regular expression
|
12
|
+
company_menu_tag: '\*\* \*\* \*\* \*\*' #use a regular expression
|
13
|
+
# Starts these transactions from blank cics in order to move forward
|
14
|
+
transactions_cics:
|
15
|
+
company_menu: 'vita'
|
16
|
+
main_application: 'life'
|
8
17
|
|
9
18
|
development:
|
10
19
|
<<: *defaults
|
@@ -1,10 +1,19 @@
|
|
1
1
|
defaults: &defaults
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
# The number of iteration through static screen
|
3
|
+
navigation_iterations: 10
|
4
|
+
cics: '7'
|
5
|
+
user: 'YOURUSER'
|
6
|
+
password: 'YOURPASSWORD'
|
7
|
+
#foo: add every variable you need and use it with => ButlerMainframe::Settings.foo
|
8
|
+
# bar: sub variable are accessible with hash => ButlerMainframe::Settings.foo[:bar]
|
9
|
+
logoff_cics: 'cesf logoff'
|
10
|
+
session_login_tag: 'EMSP00' #use a regular expression
|
11
|
+
cics_selection_tag: 'EMSP01' #use a regular expression
|
12
|
+
company_menu_tag: '\*\* \*\* \*\* \*\*' #use a regular expression
|
13
|
+
# Starts these transactions from blank cics in order to move forward
|
14
|
+
transactions_cics:
|
15
|
+
company_menu: 'vita'
|
16
|
+
main_application: 'life'
|
8
17
|
|
9
18
|
development:
|
10
19
|
<<: *defaults
|
@@ -12,6 +12,9 @@ module Host3270
|
|
12
12
|
#
|
13
13
|
# def do_quit; exec_command "CLEAR" end
|
14
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
|
15
18
|
# def destination_list
|
16
19
|
# [
|
17
20
|
# :company_menu,
|
@@ -21,6 +24,12 @@ module Host3270
|
|
21
24
|
# :back]
|
22
25
|
# end
|
23
26
|
#
|
27
|
+
# # Use navigation method to move through the static screens
|
28
|
+
# # Options:
|
29
|
+
# # :cics => ButlerMainframe::Settings.cics,
|
30
|
+
# # :user => ButlerMainframe::Settings.user,
|
31
|
+
# # :password => ButlerMainframe::Settings.password,
|
32
|
+
# # :raise_on_abend => false raise an exception if an abend is occured
|
24
33
|
# def navigate destination, options={}
|
25
34
|
# options = {
|
26
35
|
# :cics => ButlerMainframe::Settings.cics,
|
@@ -28,32 +37,50 @@ module Host3270
|
|
28
37
|
# :password => ButlerMainframe::Settings.password,
|
29
38
|
# :raise_on_abend => false
|
30
39
|
# }.merge(options)
|
31
|
-
# attempts_number
|
32
|
-
#
|
40
|
+
# attempts_number = ButlerMainframe::Settings.navigation_iterations
|
41
|
+
# transactions_cics = ButlerMainframe::Settings.transactions_cics
|
33
42
|
#
|
34
43
|
# raise "Destination #{destination} not valid, please use: #{destination_list.join(', ')}" unless destination_list.include? destination
|
35
44
|
# bol_found = nil
|
36
45
|
# attempts_number.times do
|
37
46
|
# if abend?
|
38
47
|
# options[:raise_on_abend] ? raise(catch_abend) : do_quit
|
48
|
+
# elsif company_menu?
|
49
|
+
# case destination
|
50
|
+
# when :cics_selection,
|
51
|
+
# :session_login then
|
52
|
+
# do_quit
|
53
|
+
# when :back then
|
54
|
+
# do_quit
|
55
|
+
# bol_found = true; break
|
56
|
+
# when :next then
|
57
|
+
# company_menu
|
58
|
+
# bol_found = true; break
|
59
|
+
# when :company_menu then bol_found = true; break
|
60
|
+
# else
|
61
|
+
# # Every other destination is forward
|
62
|
+
# company_menu
|
63
|
+
# end
|
39
64
|
# elsif cics?
|
40
65
|
# case destination
|
41
66
|
# when :cics_selection,
|
42
67
|
# :session_login then
|
43
|
-
# write
|
68
|
+
# write ButlerMainframe::Settings.logoff_cics, :y => 1, :x => 1
|
44
69
|
# do_enter
|
45
70
|
# when :back then
|
46
|
-
# write
|
71
|
+
# write ButlerMainframe::Settings.logoff_cics, :y => 1, :x => 1
|
47
72
|
# do_enter
|
48
73
|
# bol_found = true; break
|
49
74
|
# when :next then
|
50
|
-
# write
|
75
|
+
# write transactions_cics[:main_application], :y => 1, :x => 1
|
51
76
|
# do_enter
|
52
77
|
# bol_found = true; break
|
53
|
-
# when :company_menu then
|
78
|
+
# when :company_menu then
|
79
|
+
# write transactions_cics[:company_menu], :y => 1, :x => 1
|
80
|
+
# do_enter
|
54
81
|
# else
|
55
|
-
# #
|
56
|
-
# write
|
82
|
+
# #If we are in CICS with blank screen start the first transaction
|
83
|
+
# write transactions_cics[:main_application], :y => 1, :x => 1
|
57
84
|
# do_enter
|
58
85
|
# end
|
59
86
|
# elsif cics_selection?
|
@@ -82,15 +109,19 @@ module Host3270
|
|
82
109
|
# else
|
83
110
|
# # If we do not know where we are...
|
84
111
|
# case destination
|
85
|
-
# when
|
86
|
-
# # ...we
|
112
|
+
# when :session_login then
|
113
|
+
# # ...to come back to the first screen we surely have to go back
|
114
|
+
# go_back
|
115
|
+
# when :back then
|
116
|
+
# # ...we can try to go back (not all the screen may go back in the same way)
|
87
117
|
# go_back
|
88
118
|
# bol_found = true; break
|
89
119
|
# when :next then
|
90
120
|
# # ...but we dont know how to move forward
|
121
|
+
# raise "Define how to go forward in the navigation method on generic function module"
|
91
122
|
# else
|
92
123
|
# # We unlock the position with both commands to be sure that they are managed by all maps cics
|
93
|
-
#
|
124
|
+
# raise "Destination #{destination} not defined in the current screen"
|
94
125
|
# end
|
95
126
|
# end
|
96
127
|
# wait_session
|
@@ -99,15 +130,19 @@ module Host3270
|
|
99
130
|
# raise "It was waiting #{destination} map instead of: #{screen_title(:rows => 2).strip}" unless bol_found
|
100
131
|
# end
|
101
132
|
#
|
133
|
+
# # Check if we are the first blank cics screen
|
102
134
|
# def cics?
|
103
135
|
# scan(:y1 => 1, :x1 => 1, :y2 => 22, :x2 => 80).strip.empty?
|
104
136
|
# end
|
105
137
|
#
|
106
|
-
# #
|
138
|
+
# # Check if we are on the login mainframe screen
|
107
139
|
# def session_login?
|
108
|
-
# /
|
140
|
+
# /#{ButlerMainframe::Settings.session_login_tag}/i === screen_title
|
109
141
|
# end
|
110
142
|
#
|
143
|
+
# # Login to mainframe
|
144
|
+
# # param1 user
|
145
|
+
# # param2 password [sensible data]
|
111
146
|
# def session_login user, password
|
112
147
|
# puts "Starting session login..." if @debug
|
113
148
|
# wait_session
|
@@ -118,22 +153,41 @@ module Host3270
|
|
118
153
|
# do_enter
|
119
154
|
# end
|
120
155
|
#
|
121
|
-
# #
|
156
|
+
# # Check the label to know when we are on the cics selection map
|
122
157
|
# def cics_selection?
|
123
|
-
# /
|
158
|
+
# /#{ButlerMainframe::Settings.cics_selection_tag}/i === screen_title
|
124
159
|
# end
|
125
160
|
#
|
126
161
|
# # On this map, we have to select the cics environment
|
162
|
+
# # param1 cics usually is a number
|
127
163
|
# def cics_selection cics
|
128
164
|
# puts "Starting selezione_cics..." if @debug
|
129
165
|
# wait_session
|
130
|
-
# raise "It was waiting cics selezion map instead of: #{screen_title},
|
166
|
+
# raise "It was waiting cics selezion map instead of: #{screen_title}, message: #{catch_message}" unless cics_selection?
|
131
167
|
# write cics, :y => 23, :x => 14
|
132
168
|
# do_enter
|
133
169
|
# wait_session 1
|
134
170
|
# end
|
135
171
|
#
|
172
|
+
# # Check the label to know when we are on the cics selection map
|
173
|
+
# def company_menu?
|
174
|
+
# /#{ButlerMainframe::Settings.company_menu_tag}/i === screen_title
|
175
|
+
# end
|
136
176
|
#
|
177
|
+
# # On this map, we have to select the cics environment
|
178
|
+
# # param1 cics usually is a number
|
179
|
+
# def company_menu
|
180
|
+
# puts "Starting company menu..." if @debug
|
181
|
+
# wait_session
|
182
|
+
# raise "It was waiting company menu map instead of: #{screen_title}, message: #{catch_message}" unless company_menu?
|
183
|
+
# write "01", :y => 24, :x => 43
|
184
|
+
# do_enter
|
185
|
+
# end
|
186
|
+
#
|
187
|
+
# # Get the message line usually in the bottom of the screen
|
188
|
+
# # You can define which rows provide the message:
|
189
|
+
# # :first_row => 22,
|
190
|
+
# # :last_row => 23
|
137
191
|
# def catch_message options={}
|
138
192
|
# options = {
|
139
193
|
# :first_row => 22,
|
@@ -141,12 +195,19 @@ module Host3270
|
|
141
195
|
# }.merge(options)
|
142
196
|
# scan(:y1 => options[:first_row], :x1 => 1, :y2 => options[:last_row], :x2 => 80).gsub(/\s+/, " ").strip
|
143
197
|
# end
|
198
|
+
#
|
199
|
+
# # Get the abend message
|
144
200
|
# def catch_abend
|
145
201
|
# scan(:y1 => 23, :x1 => 1, :y2 => 23, :x2 => 80)
|
146
202
|
# end
|
203
|
+
#
|
204
|
+
# # Check if there was a malfunction on the mainframe
|
147
205
|
# def abend?
|
148
206
|
# /DFHA/i === catch_abend
|
149
207
|
# end
|
208
|
+
#
|
209
|
+
# # Get the title usually the first row
|
210
|
+
# # You can change default option :rows to get more lines starting from the first
|
150
211
|
# def screen_title options={}
|
151
212
|
# options = {
|
152
213
|
# :rows => 1
|
@@ -12,6 +12,7 @@ module Host3270
|
|
12
12
|
|
13
13
|
def do_erase; exec_command "ERASE EOF" end
|
14
14
|
|
15
|
+
# If you add your static screen you must add it in the navigation method to define how to manage it
|
15
16
|
def destination_list
|
16
17
|
[
|
17
18
|
:company_menu,
|
@@ -21,6 +22,12 @@ module Host3270
|
|
21
22
|
:back]
|
22
23
|
end
|
23
24
|
|
25
|
+
# Use navigation method to move through the static screens
|
26
|
+
# Options:
|
27
|
+
# :cics => ButlerMainframe::Settings.cics,
|
28
|
+
# :user => ButlerMainframe::Settings.user,
|
29
|
+
# :password => ButlerMainframe::Settings.password,
|
30
|
+
# :raise_on_abend => false raise an exception if an abend is occured
|
24
31
|
def navigate destination, options={}
|
25
32
|
options = {
|
26
33
|
:cics => ButlerMainframe::Settings.cics,
|
@@ -28,35 +35,54 @@ module Host3270
|
|
28
35
|
:password => ButlerMainframe::Settings.password,
|
29
36
|
:raise_on_abend => false
|
30
37
|
}.merge(options)
|
31
|
-
attempts_number
|
32
|
-
|
38
|
+
attempts_number = ButlerMainframe::Settings.navigation_iterations
|
39
|
+
transactions_cics = ButlerMainframe::Settings.transactions_cics
|
33
40
|
|
34
41
|
raise "Destination #{destination} not valid, please use: #{destination_list.join(', ')}" unless destination_list.include? destination
|
42
|
+
|
43
|
+
puts "Navigating to #{destination}" if @debug
|
35
44
|
bol_found = nil
|
36
45
|
attempts_number.times do
|
37
46
|
if abend?
|
47
|
+
puts "Navigate: abend" if @debug
|
38
48
|
options[:raise_on_abend] ? raise(catch_abend) : do_quit
|
49
|
+
elsif company_menu?
|
50
|
+
puts "Navigating to #{destination} from company menu" if @debug
|
51
|
+
case destination
|
52
|
+
when :cics_selection,
|
53
|
+
:session_login then
|
54
|
+
do_quit
|
55
|
+
when :back then
|
56
|
+
do_quit
|
57
|
+
bol_found = true; break
|
58
|
+
when :next then
|
59
|
+
company_menu
|
60
|
+
bol_found = true; break
|
61
|
+
when :company_menu then bol_found = true; break
|
62
|
+
else
|
63
|
+
# Every other destination is forward
|
64
|
+
company_menu
|
65
|
+
end
|
39
66
|
elsif cics?
|
67
|
+
puts "Navigating to #{destination} from cics" if @debug
|
40
68
|
case destination
|
41
69
|
when :cics_selection,
|
42
70
|
:session_login then
|
43
|
-
|
44
|
-
do_enter
|
71
|
+
execute_cics ButlerMainframe::Settings.logoff_cics
|
45
72
|
when :back then
|
46
|
-
|
47
|
-
do_enter
|
73
|
+
execute_cics ButlerMainframe::Settings.logoff_cics
|
48
74
|
bol_found = true; break
|
49
75
|
when :next then
|
50
|
-
|
51
|
-
do_enter
|
76
|
+
execute_cics transactions_cics[:main_application]
|
52
77
|
bol_found = true; break
|
53
|
-
when :company_menu then
|
78
|
+
when :company_menu then
|
79
|
+
execute_cics transactions_cics[:company_menu]
|
54
80
|
else
|
55
|
-
#
|
56
|
-
|
57
|
-
do_enter
|
81
|
+
#If we are in CICS with blank screen start the first transaction
|
82
|
+
execute_cics transactions_cics[:main_application]
|
58
83
|
end
|
59
84
|
elsif cics_selection?
|
85
|
+
puts "Navigating to #{destination} from cics selection" if @debug
|
60
86
|
case destination
|
61
87
|
when :cics_selection then bol_found = true; break
|
62
88
|
when :session_login then exec_command("PF3")
|
@@ -70,6 +96,7 @@ module Host3270
|
|
70
96
|
cics_selection options[:cics] if options[:cics]
|
71
97
|
end
|
72
98
|
elsif session_login?
|
99
|
+
puts "Navigating to #{destination} from session login" if @debug
|
73
100
|
case destination
|
74
101
|
when :session_login,
|
75
102
|
:back then bol_found = true; break
|
@@ -80,17 +107,22 @@ module Host3270
|
|
80
107
|
session_login options[:user], options[:password] if options[:user] && options[:password]
|
81
108
|
end
|
82
109
|
else
|
110
|
+
puts "Navigating to #{destination} from unknown screen" if @debug
|
83
111
|
# If we do not know where we are...
|
84
112
|
case destination
|
85
|
-
when
|
86
|
-
# ...we
|
113
|
+
when :session_login then
|
114
|
+
# ...to come back to the first screen we surely have to go back
|
115
|
+
go_back
|
116
|
+
when :back then
|
117
|
+
# ...we can try to go back (not all the screen may go back in the same way)
|
87
118
|
go_back
|
88
119
|
bol_found = true; break
|
89
120
|
when :next then
|
90
121
|
# ...but we dont know how to move forward
|
122
|
+
raise "Define how to go forward in the navigation method on generic function module"
|
91
123
|
else
|
92
124
|
# We unlock the position with both commands to be sure that they are managed by all maps cics
|
93
|
-
|
125
|
+
raise "Destination #{destination} not defined in the current screen"
|
94
126
|
end
|
95
127
|
end
|
96
128
|
wait_session
|
@@ -99,15 +131,19 @@ module Host3270
|
|
99
131
|
raise "It was waiting #{destination} map instead of: #{screen_title(:rows => 2).strip}" unless bol_found
|
100
132
|
end
|
101
133
|
|
134
|
+
# Check if we are the first blank cics screen
|
102
135
|
def cics?
|
103
136
|
scan(:y1 => 1, :x1 => 1, :y2 => 22, :x2 => 80).strip.empty?
|
104
137
|
end
|
105
138
|
|
106
|
-
#
|
139
|
+
# Check if we are on the login mainframe screen
|
107
140
|
def session_login?
|
108
|
-
/
|
141
|
+
/#{ButlerMainframe::Settings.session_login_tag}/i === screen_title
|
109
142
|
end
|
110
143
|
|
144
|
+
# Login to mainframe
|
145
|
+
# param1 user
|
146
|
+
# param2 password [sensible data]
|
111
147
|
def session_login user, password
|
112
148
|
puts "Starting session login..." if @debug
|
113
149
|
wait_session
|
@@ -118,22 +154,41 @@ module Host3270
|
|
118
154
|
do_enter
|
119
155
|
end
|
120
156
|
|
121
|
-
#
|
157
|
+
# Check the label to know when we are on the cics selection map
|
122
158
|
def cics_selection?
|
123
|
-
/
|
159
|
+
/#{ButlerMainframe::Settings.cics_selection_tag}/i === screen_title
|
124
160
|
end
|
125
161
|
|
126
162
|
# On this map, we have to select the cics environment
|
163
|
+
# param1 cics usually is a number
|
127
164
|
def cics_selection cics
|
128
165
|
puts "Starting selezione_cics..." if @debug
|
129
166
|
wait_session
|
130
|
-
raise "It was waiting cics selezion map instead of: #{screen_title},
|
167
|
+
raise "It was waiting cics selezion map instead of: #{screen_title}, message: #{catch_message}" unless cics_selection?
|
131
168
|
write cics, :y => 23, :x => 14
|
132
169
|
do_enter
|
133
170
|
wait_session 1
|
134
171
|
end
|
135
172
|
|
173
|
+
# Check the label to know when we are on the cics selection map
|
174
|
+
def company_menu?
|
175
|
+
/#{ButlerMainframe::Settings.company_menu_tag}/i === screen_title
|
176
|
+
end
|
177
|
+
|
178
|
+
# On this map, we have to select the cics environment
|
179
|
+
# param1 cics usually is a number
|
180
|
+
def company_menu
|
181
|
+
puts "Starting company menu..." if @debug
|
182
|
+
wait_session
|
183
|
+
raise "It was waiting company menu map instead of: #{screen_title}, message: #{catch_message}" unless company_menu?
|
184
|
+
write "01", :y => 24, :x => 43
|
185
|
+
do_enter
|
186
|
+
end
|
136
187
|
|
188
|
+
# Get the message line usually in the bottom of the screen
|
189
|
+
# You can define which rows provide the message:
|
190
|
+
# :first_row => 22,
|
191
|
+
# :last_row => 23
|
137
192
|
def catch_message options={}
|
138
193
|
options = {
|
139
194
|
:first_row => 22,
|
@@ -141,18 +196,30 @@ module Host3270
|
|
141
196
|
}.merge(options)
|
142
197
|
scan(:y1 => options[:first_row], :x1 => 1, :y2 => options[:last_row], :x2 => 80).gsub(/\s+/, " ").strip
|
143
198
|
end
|
199
|
+
|
200
|
+
# Get the abend message
|
144
201
|
def catch_abend
|
145
202
|
scan(:y1 => 23, :x1 => 1, :y2 => 23, :x2 => 80)
|
146
203
|
end
|
204
|
+
|
205
|
+
# Check if there was a malfunction on the mainframe
|
147
206
|
def abend?
|
148
207
|
/DFHA/i === catch_abend
|
149
208
|
end
|
209
|
+
|
210
|
+
# Get the title usually the first row
|
211
|
+
# You can change default option :rows to get more lines starting from the first
|
150
212
|
def screen_title options={}
|
151
213
|
options = {
|
152
214
|
:rows => 1
|
153
215
|
}.merge(options)
|
154
216
|
scan(:y1 => 1, :x1 => 1, :y2 => options[:rows], :x2 => 80)
|
155
217
|
end
|
218
|
+
|
219
|
+
def execute_cics name
|
220
|
+
write name, :y => 1, :x => 2
|
221
|
+
do_enter
|
222
|
+
end
|
156
223
|
end
|
157
224
|
|
158
225
|
end
|
@@ -12,37 +12,37 @@ module ButlerMainframe
|
|
12
12
|
def sub_create_object options={}
|
13
13
|
str_obj = 'PASSPORT.System'
|
14
14
|
puts "#{Time.now.strftime "%H:%M:%S"} Creating object #{str_obj}..." if @debug == :full
|
15
|
-
@action = WIN32OLE.new(str_obj)
|
16
|
-
@screen = @action.Sessions(@session_tag).Screen if sub_object_created?
|
15
|
+
@action[:ole] = WIN32OLE.new(str_obj)
|
16
|
+
@screen = @action[:ole].Sessions(@session_tag).Screen if sub_object_created?
|
17
17
|
end
|
18
18
|
|
19
19
|
# Check is session is started
|
20
20
|
def sub_object_created?
|
21
|
-
res = @action && @action.Sessions(@session_tag)
|
21
|
+
res = @action[:ole] && @action[:ole].Sessions(@session_tag)
|
22
22
|
puts "#{Time.now.strftime "%H:%M:%S"} Terminal successfully detected" if @debug == :full && res
|
23
23
|
res
|
24
24
|
end
|
25
25
|
|
26
26
|
# Check is session is operative
|
27
27
|
def sub_object_ready?
|
28
|
-
res = @action.Sessions(@session_tag).Connected == -1
|
28
|
+
res = @action[:ole].Sessions(@session_tag).Connected == -1
|
29
29
|
puts "#{Time.now.strftime "%H:%M:%S"} Session ready" if @debug == :full && res
|
30
30
|
res
|
31
31
|
end
|
32
32
|
|
33
33
|
def sub_name
|
34
|
-
"#{@action.Name} #{@action.Sessions(@session_tag).Name}"
|
34
|
+
"#{@action[:ole].Name} #{@action[:ole].Sessions(@session_tag).Name}"
|
35
35
|
end
|
36
36
|
|
37
37
|
def sub_fullname
|
38
|
-
"#{sub_name} #{@action.Sessions(@session_tag).FullName}"
|
38
|
+
"#{sub_name} #{@action[:ole].Sessions(@session_tag).FullName}"
|
39
39
|
end
|
40
40
|
|
41
41
|
#Ends the connection and closes the session
|
42
42
|
def sub_close_session
|
43
|
-
@action.Sessions(@session_tag).Close
|
44
|
-
@action.Quit
|
45
|
-
@action = nil
|
43
|
+
@action[:ole].Sessions(@session_tag).Close
|
44
|
+
@action[:ole].Quit
|
45
|
+
@action[:ole] = nil
|
46
46
|
end
|
47
47
|
|
48
48
|
#Execute keyboard command like PF1 or PA2 or ENTER ...
|
@@ -4,6 +4,7 @@ require 'mainframe/host_base'
|
|
4
4
|
# This class use IBM personal communication
|
5
5
|
# http://www-01.ibm.com/support/knowledgecenter/SSEQ5Y_6.0.0/welcome.html
|
6
6
|
# http://www-01.ibm.com/support/knowledgecenter/SSEQ5Y_6.0.0/com.ibm.pcomm.doc/books/html/host_access08.htm
|
7
|
+
# http://www-01.ibm.com/support/knowledgecenter/SSEQ5Y_6.0.0/com.ibm.pcomm.doc/books/html/admin_guide10.htm?lang=en
|
7
8
|
module ButlerMainframe
|
8
9
|
class Host < HostBase
|
9
10
|
|
@@ -13,39 +14,41 @@ module ButlerMainframe
|
|
13
14
|
def sub_create_object options={}
|
14
15
|
str_obj = 'PComm.autECLSession'
|
15
16
|
puts "#{Time.now.strftime "%H:%M:%S"} Creating object #{str_obj}..." if @debug == :full
|
16
|
-
@action = WIN32OLE.new(str_obj)
|
17
|
-
@action.SetConnectionByName @session_tag
|
18
|
-
@space = @action.autECLPS
|
19
|
-
@screen = @action.autECLOIA
|
17
|
+
@action[:ole] = WIN32OLE.new(str_obj)
|
18
|
+
@action[:ole].SetConnectionByName @session_tag
|
19
|
+
@space = @action[:ole].autECLPS
|
20
|
+
@screen = @action[:ole].autECLOIA
|
20
21
|
end
|
21
22
|
|
22
23
|
# Check is session is started
|
23
24
|
def sub_object_created?
|
24
|
-
res = @action && @action.CommStarted
|
25
|
+
res = @action[:ole] && @action[:ole].CommStarted
|
25
26
|
puts "#{Time.now.strftime "%H:%M:%S"} Terminal successfully detected" if @debug == :full && res
|
26
27
|
res
|
27
28
|
end
|
28
29
|
|
29
30
|
# Check is session is operative
|
30
31
|
def sub_object_ready?
|
31
|
-
res = @action.Ready
|
32
|
+
res = @action[:ole].Ready
|
32
33
|
puts "#{Time.now.strftime "%H:%M:%S"} Session ready" if @debug == :full && res
|
33
34
|
res
|
34
35
|
end
|
35
36
|
|
36
37
|
def sub_name
|
37
|
-
"PComm #{@action.Name}"
|
38
|
+
"PComm #{@action[:ole].Name}"
|
38
39
|
end
|
39
40
|
|
40
41
|
def sub_fullname
|
41
|
-
"#{sub_name} #{@action.ConnType}"
|
42
|
+
"#{sub_name} #{@action[:ole].ConnType}"
|
42
43
|
end
|
43
44
|
|
44
45
|
#Ends the connection and closes the session
|
45
46
|
def sub_close_session
|
46
|
-
@action.StopCommunication
|
47
|
-
@action = nil
|
48
|
-
|
47
|
+
@action[:ole].StopCommunication
|
48
|
+
@action[:ole] = nil
|
49
|
+
# See http://www-01.ibm.com/support/knowledgecenter/SSEQ5Y_6.0.0/com.ibm.pcomm.doc/books/html/admin_guide10.htm?lang=en
|
50
|
+
Process.spawn "PCOMSTOP /S=#{@session_tag} /q" if @pid
|
51
|
+
# Process.kill 9, @pid #Another way is to kill the process but the session start 2nd process pcscm.exe
|
49
52
|
end
|
50
53
|
|
51
54
|
#Execute keyboard command like PF1 or PA2 or ENTER ...
|
@@ -92,13 +92,13 @@ module ButlerMainframe
|
|
92
92
|
:check_protect => true
|
93
93
|
}.merge(options)
|
94
94
|
sub_set_cursor_axes y, x
|
95
|
-
x_cmd "String(#{text})"
|
95
|
+
x_cmd "String(\"#{text}\")", options
|
96
96
|
# TODO
|
97
97
|
# if options[:check_protect]
|
98
98
|
# end
|
99
99
|
end
|
100
100
|
|
101
|
-
# Wait text at given coordinates
|
101
|
+
# Wait text at given coordinates
|
102
102
|
def sub_wait_for_string text, y, x
|
103
103
|
x_cmd "Wait(#{@timeout},InputField)"
|
104
104
|
total_time = 0.0
|
@@ -109,12 +109,12 @@ module ButlerMainframe
|
|
109
109
|
# @timeout should be in milliseconds but everything is possible
|
110
110
|
break if total_time >= @timeout
|
111
111
|
end
|
112
|
-
|
113
|
-
true
|
112
|
+
sub_scan_row(y, x, text.size) == text
|
114
113
|
end
|
115
114
|
|
116
|
-
|
117
|
-
|
115
|
+
# To communicate with executable
|
116
|
+
def x_cmd cmd, options={}
|
117
|
+
puts "x_cmd in: #{options[:sensible_data] ? ('*' * cmd.size) : cmd}" if @debug == :full
|
118
118
|
@action[:in].print "#{cmd}\n"
|
119
119
|
@action[:in].flush
|
120
120
|
|
@@ -123,7 +123,7 @@ module ButlerMainframe
|
|
123
123
|
|
124
124
|
line, str_out = '', ''
|
125
125
|
while line = @action[:out].gets.chomp do
|
126
|
-
puts "x_cmd out: '#{line}'" if @debug
|
126
|
+
puts "x_cmd out: '#{line}'" if @debug == :full
|
127
127
|
break if ar_res.include? line
|
128
128
|
str_out << "#{line[6..-1]}" if /^data:\s/ === line
|
129
129
|
end
|
data/lib/mainframe/host_base.rb
CHANGED
@@ -14,7 +14,7 @@ module ButlerMainframe
|
|
14
14
|
:session_tag => ButlerMainframe.configuration.session_tag,
|
15
15
|
:wait => 0.01, #wait screen in seconds
|
16
16
|
:wait_debug => 2, #wait time for debug purpose
|
17
|
-
:debug =>
|
17
|
+
:debug => false,
|
18
18
|
:browser_path => ButlerMainframe.configuration.browser_path,
|
19
19
|
:session_url => ButlerMainframe.configuration.session_url,
|
20
20
|
:session_path => ButlerMainframe.configuration.session_path,
|
@@ -31,6 +31,7 @@ module ButlerMainframe
|
|
31
31
|
@session_tag = options[:session_tag]
|
32
32
|
@close_session = options[:close_session]
|
33
33
|
@timeout = options[:timeout]
|
34
|
+
@action = {}
|
34
35
|
@pid = nil
|
35
36
|
|
36
37
|
create_object options
|
@@ -87,19 +88,32 @@ module ButlerMainframe
|
|
87
88
|
|
88
89
|
# Write text on screen at the coordinates
|
89
90
|
# Based on the parameters provided it writes a line or an area
|
91
|
+
# Options:
|
92
|
+
# :hook => nil,
|
93
|
+
# :y => nil, #row
|
94
|
+
# :x => nil, #column
|
95
|
+
# :check => true,
|
96
|
+
# :raise_error_on_check => true,
|
97
|
+
# :sensible_data => nil,
|
98
|
+
# :clean_first_chars => nil, # clean x chars before writing a value
|
99
|
+
# :erase_field_first => nil # erase first until end of field
|
90
100
|
def write text, options={}
|
91
101
|
options = {
|
92
102
|
:hook => nil,
|
93
|
-
:y => nil, #
|
94
|
-
:x => nil, #
|
103
|
+
:y => nil, #row
|
104
|
+
:x => nil, #column
|
95
105
|
:check => true,
|
96
106
|
:raise_error_on_check => true,
|
97
107
|
:sensible_data => nil,
|
98
|
-
:clean_first_chars => nil # clean x chars before writing a value
|
108
|
+
:clean_first_chars => nil, # clean x chars before writing a value
|
109
|
+
:erase_field_first => nil # erase first until end of field
|
99
110
|
}.merge(options)
|
100
111
|
|
101
112
|
y = options[:y]
|
102
113
|
x = options[:x]
|
114
|
+
y ||= get_cursor_axes[0]
|
115
|
+
x ||= get_cursor_axes[1]
|
116
|
+
|
103
117
|
hooked_rows = 2
|
104
118
|
raise "Missing coordinates! y(row)=#{y} x(column)=#{x} " unless x && y
|
105
119
|
raise "Sorry, cannot write null values" unless text
|
@@ -135,14 +149,14 @@ module ButlerMainframe
|
|
135
149
|
# It creates the object calling subclass method
|
136
150
|
# It depends on the emulator chosen but typically the object is present after starting the terminal session
|
137
151
|
# These are the options with default values:
|
138
|
-
# :
|
139
|
-
# :debug =>
|
140
|
-
# :browser_path => ButlerMainframe::Settings.browser_path,
|
141
|
-
# :session_path => ButlerMainframe::Settings.session_path,
|
152
|
+
# :session_tag => Fixnum, String or null depending on emulator
|
153
|
+
# :debug => boolean
|
142
154
|
def create_object options={}
|
143
|
-
connection_attempts =
|
144
|
-
seconds_between_attempts =
|
155
|
+
connection_attempts = 10
|
156
|
+
seconds_between_attempts = 1
|
145
157
|
|
158
|
+
# Creating session object for emulators managed by API
|
159
|
+
# Some emulator may start session terminal and return a process id in @pid
|
146
160
|
sub_create_object options
|
147
161
|
|
148
162
|
if sub_object_created?
|
@@ -151,23 +165,10 @@ module ButlerMainframe
|
|
151
165
|
# if the terminal is not found then we start it
|
152
166
|
puts "Session #{@session_tag} not found, starting new..." if @debug
|
153
167
|
|
154
|
-
executable,
|
155
|
-
|
156
|
-
elsif options[:session_path] && !options[:session_path].empty?
|
157
|
-
[options[:session_path], nil]
|
158
|
-
else
|
159
|
-
[nil, nil]
|
160
|
-
end
|
161
|
-
raise "Specify an executable in the configuration file!" unless executable
|
162
|
-
|
163
|
-
if /^1.8/ === RUBY_VERSION
|
164
|
-
Thread.new {system "#{executable} #{args}"}
|
165
|
-
@pid = $?.pid if $?
|
166
|
-
else
|
167
|
-
#It works only on ruby 1.9+
|
168
|
-
@pid = Process.spawn *[executable, args].compact
|
169
|
-
end
|
168
|
+
# Starting executable, check configuration file
|
169
|
+
start_terminal_session options
|
170
170
|
|
171
|
+
# New connection attempts after starting session...
|
171
172
|
puts "Starting session with process id #{@pid}, wait please..." if @debug
|
172
173
|
sleep 2
|
173
174
|
connection_attempts.times do
|
@@ -179,6 +180,7 @@ module ButlerMainframe
|
|
179
180
|
|
180
181
|
raise "Session #{@session_tag} not started. Check the session #{options[:browser_path]} #{options[:session_path]}" unless sub_object_created?
|
181
182
|
|
183
|
+
# Session detected and waiting it become operative
|
182
184
|
unless sub_object_ready?
|
183
185
|
connection_attempts.times do
|
184
186
|
puts "Waiting for the session to be ready..." if @debug
|
@@ -186,11 +188,12 @@ module ButlerMainframe
|
|
186
188
|
end
|
187
189
|
end
|
188
190
|
|
191
|
+
# At this stage the session must be operative otherwise raise an exception
|
189
192
|
if sub_object_ready?
|
190
193
|
puts "** Connection established with #{sub_name} **"
|
191
194
|
puts "Session full name: #{sub_fullname}" if @debug == :full
|
192
195
|
else
|
193
|
-
raise "Connection refused. Check session #{@session_tag} with process id #{@pid}"
|
196
|
+
raise "Connection refused. Check session #{@session_tag}#{" with process id #{@pid}" if @pid}!"
|
194
197
|
end
|
195
198
|
|
196
199
|
rescue
|
@@ -198,6 +201,31 @@ module ButlerMainframe
|
|
198
201
|
raise $!
|
199
202
|
end
|
200
203
|
|
204
|
+
# Starting terminal session
|
205
|
+
# Options:
|
206
|
+
# :browser_path => browser executable path, default value ButlerMainframe::Settings.browser_path (used by web emulator)
|
207
|
+
# :session_url => the session url used by browser
|
208
|
+
# :session_path => terminal session executable path, default value ButlerMainframe::Settings.session_path
|
209
|
+
def start_terminal_session options
|
210
|
+
# Check configuration to know emulator starting type
|
211
|
+
executable, args = if options[:browser_path] && !options[:browser_path].empty?
|
212
|
+
[options[:browser_path], options[:session_url]]
|
213
|
+
elsif options[:session_path] && !options[:session_path].empty?
|
214
|
+
[options[:session_path], nil]
|
215
|
+
else
|
216
|
+
[nil, nil]
|
217
|
+
end
|
218
|
+
raise "Specify an executable in the configuration file!" unless executable
|
219
|
+
|
220
|
+
if /^1.8/ === RUBY_VERSION
|
221
|
+
Thread.new {system "#{executable} #{args}"}
|
222
|
+
@pid = $?.pid if $?
|
223
|
+
else
|
224
|
+
#It works only on ruby 1.9+
|
225
|
+
@pid = Process.spawn *[executable, args].compact
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
201
229
|
#It reads one line on the screen
|
202
230
|
def scan_row y, x, len
|
203
231
|
str = sub_scan_row y, x, len
|
data/test/test.rake
CHANGED
@@ -6,21 +6,107 @@ namespace :butler do
|
|
6
6
|
desc "Test butler mainframe gem"
|
7
7
|
task(:test) do |task_name, args|
|
8
8
|
|
9
|
+
host = nil
|
9
10
|
begin
|
10
11
|
require 'butler-mainframe'
|
11
|
-
|
12
|
-
str_screen1 = host.scan_page
|
13
|
-
raise 'host.scan_page' if str_screen1.empty?
|
14
|
-
host.navigate :next
|
15
|
-
str_screen2 = host.scan_page
|
16
|
-
raise 'host.navigate :next' if str_screen1 == str_screen2
|
17
|
-
host.close_session
|
12
|
+
wait_between_iterations = 3
|
18
13
|
|
14
|
+
# SLOW
|
15
|
+
simple_iteration :wait => 0.6
|
16
|
+
sleep(wait_between_iterations)
|
17
|
+
|
18
|
+
# MEDIUM
|
19
|
+
simple_iteration :wait => 0.08
|
20
|
+
sleep(wait_between_iterations)
|
21
|
+
|
22
|
+
# FAST (default 0.01 atm)
|
23
|
+
simple_iteration
|
24
|
+
sleep(wait_between_iterations)
|
25
|
+
|
26
|
+
puts "*** RAKE TESTS COMPLETE SUCCESSFULLY ***"
|
19
27
|
rescue
|
20
28
|
puts $!.message
|
29
|
+
puts "--- RAKE TESTS FAILED ---"
|
21
30
|
exit(9)
|
22
31
|
end
|
23
32
|
end
|
24
33
|
|
25
34
|
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def simple_iteration options={}
|
38
|
+
options = {
|
39
|
+
:host => nil,
|
40
|
+
:wait => nil
|
41
|
+
|
42
|
+
}.merge(options)
|
43
|
+
|
44
|
+
puts
|
45
|
+
puts "*** START ITERATION TEST WAIT #{options[:wait] || 'DEFAULT'} ***"
|
46
|
+
params = {:debug => false, :wait_debug => 0.5}
|
47
|
+
params[:wait] = options[:wait] if options[:wait]
|
48
|
+
host = options[:host] || ButlerMainframe::Host.new(params)
|
49
|
+
|
50
|
+
navigate host, :session_login
|
51
|
+
|
52
|
+
str_screen1 = host.scan_page
|
53
|
+
raise 'host.scan_page' if str_screen1.empty?
|
54
|
+
|
55
|
+
navigate host, :next
|
56
|
+
str_screen2 = host.scan_page
|
57
|
+
raise 'navigate :next does not pass login screen' if str_screen1 == str_screen2
|
58
|
+
|
59
|
+
navigate host, :next
|
60
|
+
str_screen2 = host.scan_page
|
61
|
+
raise 'navigate :next does not pass cics selection' if str_screen1 == str_screen2
|
62
|
+
|
63
|
+
# Go back until the first screen
|
64
|
+
navigate host, :session_login
|
65
|
+
|
66
|
+
raise "host.scan row failed" unless host.scan(:y => 1, :x => 1, :len => 80).size == 80
|
67
|
+
raise "host.scan area failed" unless host.scan(:y1 => 1, :x1 => 1, :y2 => 3, :x2 => 80).size == 240
|
68
|
+
|
69
|
+
navigate host, :back
|
70
|
+
|
71
|
+
navigate host, :company_menu
|
72
|
+
|
73
|
+
navigate host, :next
|
74
|
+
|
75
|
+
navigate host, :back
|
76
|
+
|
77
|
+
navigate host, :back
|
78
|
+
|
79
|
+
navigate host, :company_menu
|
80
|
+
|
81
|
+
navigate host, :back
|
82
|
+
|
83
|
+
navigate host, :back
|
84
|
+
|
85
|
+
navigate host, :session_login
|
86
|
+
|
87
|
+
navigate host, :cics_selection
|
88
|
+
|
89
|
+
navigate host, :next
|
90
|
+
|
91
|
+
navigate host, :back
|
92
|
+
|
93
|
+
navigate host, :back
|
94
|
+
|
95
|
+
navigate host, :session_login
|
96
|
+
|
97
|
+
navigate host, :company_menu
|
98
|
+
|
99
|
+
navigate host, :cics_selection
|
100
|
+
|
101
|
+
navigate host, :session_login
|
102
|
+
|
103
|
+
host.close_session
|
104
|
+
end
|
105
|
+
|
106
|
+
# Easy navigation for rake test
|
107
|
+
def navigate host, action
|
108
|
+
msg = "Rake Navigate to #{action}: "
|
109
|
+
print msg
|
110
|
+
host.navigate action
|
111
|
+
puts "#{' ' * (40 - msg.size).abs}OK"
|
26
112
|
end
|
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.
|
4
|
+
version: 0.3.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-
|
11
|
+
date: 2015-10-22 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. You just have to choose your emulator (atm only one choice)
|