te3270 0.8.1 → 0.9.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
- SHA1:
3
- metadata.gz: 0b8ddf072f9f9cd64003ca654af024ad1b6fe2c6
4
- data.tar.gz: e78254e04a34431a4da5c4376c860ef06f3c75e6
2
+ SHA256:
3
+ metadata.gz: ca80832f6e8d872ddeb31fbc12a29ad613ad33ef13b191b9c6cb2f289cbca413
4
+ data.tar.gz: 36961aadfe3fcf1bf2fc569d1622c48d943aa1b2cc71df24c56cb3232d7d572b
5
5
  SHA512:
6
- metadata.gz: 478e2822e1b6777d2c353084cadd5ec2bcbef3af290972e38ff9bdb8c676260a15227670a8e878d55e8bdcc22c90ac8f387a5ae9fb30d7da83c0ac0f5afa9ca9
7
- data.tar.gz: e94556825730d4176b08d98d880437e1028aac498df571c488b94a8d79f694b8f00c8f402ce8387240ff3a498b592e5c6600ea3cc9fa9fa2be7cdcb3309867cf
6
+ metadata.gz: '08839017d9d96ad934cbd2295a55aff3e3470aacbe8771139b7429d724119aa75f41a91e998e229e3d890d26d4718f22e690d84abfbb60dc0f938e1080b87ef7'
7
+ data.tar.gz: c13d41c841a084a4b04a6ba29cf27a35f03ae944c3f453563d8da140a492b7b43aa1ab808a7c9359ab7696a57fc00e8052eae2c6b386c816b336610cf0f3a4de
data/ChangeLog CHANGED
@@ -1,3 +1,11 @@
1
+ === Version 0.9.0 / 2020-03-19
2
+ * Enhancements
3
+ * Added support for BlueZone driver (Thanks Jonathan Knapp)
4
+ * Add troubleshooting info to README
5
+ * Fixes
6
+ * No longer limit bundler version in dev dependency
7
+ * Fix test that only runs on windows
8
+
1
9
  === Version 0.8.1 / 2017-03-06
2
10
  * Fixes
3
11
  * Fixed get_string method for Virtel (Thanks David West)
data/README.md CHANGED
@@ -1,11 +1,13 @@
1
1
  # TE3270
2
2
 
3
- This gem can be used to drive a 3270 terminal emulator. You have to have a supported emulator installed on the
4
- machines on which you use the gem. Currently the supported emulators are
3
+ This gem can be used to drive a 3270 terminal emulator. You have to have a supported emulator installed on the
4
+ machines on which you use the gem. Currently the supported emulators are
5
5
  [EXTRA! X-treme](http://www.attachmate.com/Products/Terminal+Emulation/Extra/xtreme/extra-x-treme.htm) by
6
- Attachmate, [Quick3270](http://www.dn-computing.com/Quick3270.htm) by DN-Computing, [Virtel Web Access](http://www.virtelweb.com/solutions/3270-terminal-emulation.html),
6
+ Attachmate, [Quick3270](http://www.dn-computing.com/Quick3270.htm) by DN-Computing,
7
+ [Rocket BlueZone](https://www.rocketsoftware.com/products/rocket-bluezonepassport-terminal-emulator/rocket-bluezone-terminal-emulation),
8
+ [Virtel Web Access](http://www.virtelweb.com/solutions/3270-terminal-emulation.html),
7
9
  and [X3270](http://x3270.bgp.nu/).
8
- The first three are commercial products and need to be purchased.
10
+ The first four are commercial products and need to be purchased.
9
11
  X3270 is open source. Support for other
10
12
  emulators will be added as time permits.
11
13
 
@@ -29,7 +31,7 @@ Or install it yourself as:
29
31
 
30
32
  ## Usage
31
33
 
32
- You can create classes that are similar to page-object classes. In these classes you can define
34
+ You can create classes that are similar to page-object classes. In these classes you can define
33
35
  the various fields that you wish to interact with on the screen.
34
36
 
35
37
  class MainframeScreen
@@ -90,9 +92,9 @@ or you can use the version of `on` that takes a block like this:
90
92
  screen.password = 'the_password'
91
93
  end
92
94
 
93
- There is also a way to pass in a `Hash` and have it populate an entire screen. Just simply
95
+ There is also a way to pass in a `Hash` and have it populate an entire screen. Just simply
94
96
  ensure the key for an entry in the `Hash` matches the name you gave a text field and it will
95
- find and set the value. This allows the gem to easily work with the DataMagic gem.
97
+ find and set the value. This allows the gem to easily work with the DataMagic gem.
96
98
 
97
99
  # given this Hash
98
100
  my_data = { userid: 'the_id', password: 'the_password' }
@@ -100,6 +102,19 @@ find and set the value. This allows the gem to easily work with the DataMagic g
100
102
  # you can simply call this method
101
103
  on(MainframeScreen).populate_screen_with my_data
102
104
 
105
+ ## Troubleshooting
106
+
107
+ If you plan to use the BlueZone emulator support, make sure the version of BlueZone
108
+ that you install matches the architecture of the Ruby version you are using.
109
+
110
+ _ex: x86 for both or 64 bit for both_
111
+
112
+ Also, if you intend to take screenshots with BlueZone, Extra, or Quick emulators
113
+ you will need to use the x86 version of Ruby as the 64 bit version of
114
+ [win32screenshot](https://rubygems.org/gems/win32screenshot/) depends on
115
+ [rautomation](https://rubygems.org/gems/rautomation/) which
116
+ [does not support 64 bit installs](https://github.com/jarmo/RAutomation/issues/68)
117
+ at this time.
103
118
 
104
119
  ## Contributing
105
120
 
@@ -1,3 +1,4 @@
1
+ require 'te3270/emulators/bluezone'
1
2
  require 'te3270/emulators/extra'
2
3
  require 'te3270/emulators/quick3270'
3
4
  require 'te3270/emulators/x3270'
@@ -11,6 +12,7 @@ module TE3270
11
12
  module EmulatorFactory
12
13
 
13
14
  EMULATORS = {
15
+ bluezone: TE3270::Emulators::BlueZone,
14
16
  extra: TE3270::Emulators::Extra,
15
17
  quick3270: TE3270::Emulators::Quick3270,
16
18
  x3270: TE3270::Emulators::X3270,
@@ -22,4 +24,4 @@ module TE3270
22
24
  end
23
25
 
24
26
  end
25
- end
27
+ end
@@ -0,0 +1,282 @@
1
+ module TE3270
2
+ module Emulators
3
+ class BlueZoneError < StandardError; end
4
+ class InvalidVisibleStateError < BlueZoneError; end
5
+ class InvalidWindowStateError < BlueZoneError; end
6
+ class InvalidWriteMethodError < BlueZoneError; end
7
+ class SessionFileMissingError < BlueZoneError; end
8
+ class Win32OleRuntimeError < BlueZoneError; end
9
+
10
+ #
11
+ # This class has the code necessary to communicate with the terminal emulator called Rocket BlueZone.
12
+ # You can use this emulator by providing the +:bluezone+ parameter to the constructor of your screen
13
+ # object or by passing the same value to the +emulator_for+ method on the +TE3270+ module.
14
+ #
15
+ class BlueZone
16
+ attr_writer :connect_retry_timeout,
17
+ :max_column_length,
18
+ :max_wait_time,
19
+ :session_id,
20
+ :session_file,
21
+ :timeout,
22
+ :write_errors_to_ignore,
23
+ :write_method
24
+
25
+ #
26
+ # Initialize the emulator with defaults. This also loads libraries used
27
+ # to take screenshots on supported platforms.
28
+ #
29
+ def initialize
30
+ @connect_retry_timeout = 30
31
+ @max_column_length = 80
32
+ @max_wait_time = 100
33
+ @session_file = nil
34
+ @session_id = 1
35
+ @timeout = 10
36
+ @visible = true
37
+ @window_state = :normal
38
+ @write_errors_to_ignore = [5, 6]
39
+ @write_method = :full_string
40
+
41
+ if jruby?
42
+ require 'jruby-win32ole'
43
+ require 'java'
44
+ include_class 'java.awt.Dimension'
45
+ include_class 'java.awt.Rectangle'
46
+ include_class 'java.awt.Robot'
47
+ include_class 'java.awt.Toolkit'
48
+ include_class 'java.awt.event.InputEvent'
49
+ include_class 'java.awt.image.BufferedImage'
50
+ include_class 'javax.imageio.ImageIO'
51
+ else
52
+ require 'win32ole'
53
+ require 'win32/screenshot'
54
+ end
55
+ end
56
+
57
+ #
58
+ # Creates a method to connect to BlueZone. This method expects a block in which certain
59
+ # platform specific values can be set. BlueZone can take the following parameters.
60
+ #
61
+ # * connect_retry_timeout - number of seconds to retry connecting to a session. Defaults to +30+.
62
+ # * max_column_length - number of columns in a terminal row. Defaults to +80+.
63
+ # * max_wait_time - number of milliseconds to wait before resuming script execution after sending keys from host. Defaults to +100+.
64
+ # * session_file - this value is required and should be the filename of the session.
65
+ # * session_id - numeric identifier for type of session to connect to. From BlueZone's docs: +1 for S1: 2 for S2; 3 for S3; etc.+ Defaults to +1+.
66
+ # * timeout - numeric number of seconds till system calls timeout. Defaults to +10+.
67
+ # * visible - determines if the emulator is visible or not. If not set it will default to +true+.
68
+ # * window_state - determines the state of the session window. Valid values are +:minimized+,
69
+ # +:normal+, and +:maximized+. If not set it will default to +:normal+.
70
+ # * write_errors_to_ignore - array of error codes to ignore during "char" write method. Defaults to +[5, 6]+.
71
+ # * write_method - write strings to the terminal all at once or one character at a time Valid values are +:full_string+,
72
+ # and +:char+. Default is +:full_string+.
73
+ #
74
+ # @example Example calling screen object constructor with a block
75
+ # screen_object = MyScreenObject.new(:bluezone)
76
+ # screen_object.connect do |emulator|
77
+ # emulator.session_file = 'path_to_session_file'
78
+ # emulator.visible = true
79
+ # emulator.window_state = :maximized
80
+ # end
81
+ #
82
+ def connect
83
+ start_bluezone_system
84
+ yield self if block_given?
85
+ raise InvalidWriteMethodError unless [:char, :full_string].include?(@write_method)
86
+ raise SessionFileMissingError if @session_file.nil?
87
+
88
+ result = system.OpenSession(SESSION_TYPE[:Mainframe], @session_id, @session_file, @timeout, 1)
89
+ raise BlueZoneError, "Error opening session: #{result}; #{@session_file}" if result != 0
90
+
91
+ result = system.Connect('!', @connect_retry_timeout)
92
+ raise BlueZoneError, "Error connecting to session: #{result}" if result != 0
93
+ end
94
+
95
+ #
96
+ # Disconnects the BlueZone connection
97
+ #
98
+ def disconnect
99
+ system.CloseSession(SESSION_TYPE[:Mainframe], @session_id)
100
+ end
101
+
102
+ #
103
+ # Extracts text of specified length from a start point.
104
+ #
105
+ # @param [Fixnum] row the x coordinate of location on the screen.
106
+ # @param [Fixnum] column the y coordinate of location on the screen.
107
+ # @param [Fixnum] length the length of string to extract
108
+ # @return [String]
109
+ #
110
+ def get_string(row, column, length)
111
+ system.PSGetText(length, ((row - 1) * @max_column_length) + column)
112
+ end
113
+
114
+ #
115
+ # Puts string at the coordinates specified.
116
+ #
117
+ # @param [String|Fixnum] input the value to set; value is cast to string
118
+ # @param [Fixnum] row the x coordinate of the location on the screen.
119
+ # @param [Fixnum] column the y coordinate of the location on the screen.
120
+ #
121
+ def put_string(input, row, column)
122
+ input_as_string = input.to_s
123
+
124
+ if @write_method == :full_string
125
+ system.WriteScreen(input_as_string, row, column)
126
+ system.WaitReady(@timeout, @max_wait_time)
127
+ elsif @write_method == :char
128
+ input_as_string.chars.each_with_index do |char, index|
129
+ position = ((row - 1) * @max_column_length) + column + index
130
+ position_row = (position / @max_column_length.to_f).ceil
131
+ position_col = position % @max_column_length
132
+ position_col = position_col == 0 ? @max_column_length : position_col
133
+ result = system.WriteScreen(char, position_row, position_col)
134
+ break unless ([0] + @write_errors_to_ignore).include?(result)
135
+ system.WaitReady(@timeout, @max_wait_time)
136
+ end
137
+ else
138
+ raise InvalidWriteMethodError, @write_method
139
+ end
140
+ end
141
+
142
+ #
143
+ # Creates a method to take screenshot of the active screen. If you have set the +:visible+
144
+ # property to false it will be made visible prior to taking the screenshot and then changed
145
+ # to invisible after.
146
+ #
147
+ # @param [String] filename the path and name of the screenshot file to be saved
148
+ #
149
+ def screenshot(filename)
150
+ File.delete(filename) if File.exists?(filename)
151
+ original_visibility = @visible
152
+ self.visible = true
153
+
154
+ if jruby?
155
+ toolkit = Toolkit::getDefaultToolkit()
156
+ screen_size = toolkit.getScreenSize()
157
+ rect = Rectangle.new(screen_size)
158
+ robot = Robot.new
159
+ image = robot.createScreenCapture(rect)
160
+ f = java::io::File.new(filename)
161
+ ImageIO::write(image, "png", f)
162
+ else
163
+ hwnd = system.WindowHandle
164
+ Win32::Screenshot::Take.of(:window, hwnd: hwnd).write(filename)
165
+ end
166
+
167
+ self.visible = false unless original_visibility
168
+ end
169
+
170
+ #
171
+ # Sends keystrokes to the host, including function keys.
172
+ #
173
+ # @param [String] keys keystokes up to 255 in length
174
+ #
175
+ def send_keys(keys)
176
+ system.SendKey(keys)
177
+ system.WaitReady(@timeout, @max_wait_time)
178
+ end
179
+
180
+ #
181
+ # Returns the text of the active screen
182
+ #
183
+ # @return [String]
184
+ #
185
+ def text
186
+ system.PSText
187
+ end
188
+
189
+ #
190
+ # Sets the currently connected windows visibility.
191
+ #
192
+ # @param [Bool] value
193
+ #
194
+ def visible=(value)
195
+ raise InvalidVisibleStateError, value unless [false, true].include?(value)
196
+
197
+ @visible = value
198
+ window = system.Window
199
+ window.Visible = value
200
+ end
201
+
202
+ #
203
+ # Waits for the host to not send data for a specified number of seconds
204
+ #
205
+ # @param [Fixnum] seconds the maximum number of seconds to wait
206
+ #
207
+ def wait_for_host(seconds)
208
+ system.Wait(seconds)
209
+ end
210
+
211
+ #
212
+ # Wait for the string to appear at the specified location
213
+ #
214
+ # @param [String] str the string to wait for
215
+ # @param [Fixnum] row the x coordinate of location
216
+ # @param [Fixnum] column the y coordinate of location
217
+ #
218
+ def wait_for_string(str, row, column)
219
+ system.WaitForText(str, row, column, @timeout)
220
+ end
221
+
222
+ #
223
+ # Waits until the cursor is at the specified location.
224
+ #
225
+ # @param [Fixnum] row the x coordinate of the location
226
+ # @param [Fixnum] column the y coordinate of the location
227
+ #
228
+ def wait_until_cursor_at(row, column)
229
+ system.WaitCursor(@timeout, row, column, 3)
230
+ end
231
+
232
+ #
233
+ # Sets the currently connected windows state.
234
+ #
235
+ # @param [Symbol] state
236
+ #
237
+ def window_state=(state)
238
+ raise InvalidWindowStateError, state unless WINDOW_STATE.keys.include?(state)
239
+
240
+ @window_state = state
241
+ system.WindowState = WINDOW_STATE[state]
242
+ end
243
+
244
+ private
245
+
246
+ SESSION_TYPE = {
247
+ Mainframe: 0,
248
+ iSeries: 1,
249
+ VT: 2,
250
+ UTS: 3,
251
+ T27: 4,
252
+ '6530': 6
253
+ }.freeze
254
+
255
+ WINDOW_STATE = {
256
+ maximized: 2,
257
+ minimized: 1,
258
+ normal: 0
259
+ }.freeze
260
+
261
+ attr_reader :system
262
+
263
+ def jruby?
264
+ RUBY_PLATFORM == 'java'
265
+ end
266
+
267
+ def start_bluezone_system
268
+ begin
269
+ @system = WIN32OLE.new('BZWhll.WhllObj')
270
+
271
+ # Default window state.
272
+ # Once session is "connected" these will be applied unless overwritten.
273
+ self.window_state = @window_state
274
+ self.visible = @visible
275
+ rescue Win32OleRuntimeError => exception
276
+ $stderr.puts exception
277
+ raise MissingOleRuntimeError, 'Unable to find BZWhll.WhllObj OLE runtime. Did you install the same BlueZone Desktop architecture as your Ruby runtime? ex: x86 vs 64 bit'
278
+ end
279
+ end
280
+ end
281
+ end
282
+ end
@@ -1,3 +1,3 @@
1
1
  module TE3270
2
- VERSION = "0.8.1"
2
+ VERSION = "0.9.0"
3
3
  end
@@ -0,0 +1,330 @@
1
+ require 'spec_helper'
2
+
3
+ describe TE3270::Emulators::BlueZone do
4
+
5
+ unless Gem.win_platform?
6
+ class WIN32OLE
7
+ end
8
+ end
9
+
10
+ let(:bluezone) do
11
+ allow_any_instance_of(TE3270::Emulators::BlueZone).to receive(:require) unless Gem.win_platform?
12
+ TE3270::Emulators::BlueZone.new
13
+ end
14
+
15
+ before(:each) do
16
+ allow(WIN32OLE).to receive(:new).and_return bluezone_system
17
+ bluezone.instance_variable_set(:@session_file, 'the_file')
18
+ allow(File).to receive(:exists).and_return false
19
+ end
20
+
21
+
22
+ describe "global behaviors" do
23
+ it 'should start a new terminal' do
24
+ expect(WIN32OLE).to receive(:new).and_return(bluezone_system)
25
+ bluezone.connect
26
+ end
27
+
28
+ it 'should open a session' do
29
+ expect(bluezone_system).to receive(:OpenSession).and_return(0)
30
+ bluezone.connect
31
+ end
32
+
33
+ it 'should call a block allowing the session file to be set' do
34
+ expect(bluezone_system).to receive(:OpenSession).with(0, 1, 'blah.edp', 10, 1).and_return(0)
35
+ bluezone.connect do |platform|
36
+ platform.session_file = 'blah.edp'
37
+ end
38
+ end
39
+
40
+ it 'should call a block with custom session number to be set' do
41
+ expect(bluezone_system).to receive(:OpenSession).with(0, 2, 'blah.edp', 10, 1).and_return(0)
42
+ bluezone.connect do |platform|
43
+ platform.session_id = 2
44
+ platform.session_file = 'blah.edp'
45
+ end
46
+ end
47
+
48
+ it 'should raise an error when the session file is not set' do
49
+ bluezone.instance_variable_set(:@session_file, nil)
50
+ expect { bluezone.connect }.to raise_error(TE3270::Emulators::SessionFileMissingError)
51
+ end
52
+
53
+ it 'should take the visible value from a block' do
54
+ expect(bluezone_window).to receive(:Visible=).with(false)
55
+ bluezone.connect do |platform|
56
+ platform.visible = false
57
+ end
58
+ end
59
+
60
+ it 'should default to visible when not specified' do
61
+ expect(bluezone_window).to receive(:Visible=).with(true)
62
+ bluezone.connect
63
+ end
64
+
65
+ it 'should take the window state value from the block' do
66
+ expect(bluezone_system).to receive(:WindowState=).with(2)
67
+ bluezone.connect do |platform|
68
+ platform.window_state = :maximized
69
+ end
70
+ end
71
+
72
+ it 'should default to window state normal when not specified' do
73
+ expect(bluezone_system).to receive(:WindowState=).with(0)
74
+ bluezone.connect
75
+ end
76
+
77
+ it 'should get the connection for the active session' do
78
+ expect(bluezone_system).to receive(:Connect).with("!", 30).and_return(0)
79
+ bluezone.connect
80
+ end
81
+
82
+ it 'should get the connection with custom connection retry timeout for the active session' do
83
+ expect(bluezone_system).to receive(:Connect).with("!", 0).and_return(0)
84
+ bluezone.connect_retry_timeout = 0
85
+ bluezone.connect
86
+ end
87
+
88
+ it 'should disconnect from a session' do
89
+ expect(bluezone_system).to receive(:CloseSession).with(0, 1)
90
+ bluezone.connect
91
+ bluezone.disconnect
92
+ end
93
+
94
+ it 'should disconnect from a custom session id' do
95
+ expect(bluezone_system).to receive(:CloseSession).with(0, 2)
96
+ bluezone.connect do |platform|
97
+ platform.session_id = 2
98
+ end
99
+ bluezone.disconnect
100
+ end
101
+
102
+ it 'should set write_method to :full_string by default' do
103
+ expect(bluezone.instance_variable_get(:@write_method)).to eq(:full_string)
104
+ end
105
+
106
+ it 'should allow setting write_method to :char' do
107
+ bluezone.connect do |platform|
108
+ platform.write_method = :char
109
+ end
110
+ expect(bluezone.instance_variable_get(:@write_method)).to eq(:char)
111
+ end
112
+
113
+ it 'should raise InvalidWriteMethodError with invalid write_method' do
114
+ bluezone.instance_variable_set(:@write_method, nil)
115
+ expect { bluezone.connect }.to raise_error(TE3270::Emulators::InvalidWriteMethodError)
116
+
117
+ bluezone.instance_variable_set(:@write_method, :invalid)
118
+ expect { bluezone.connect }.to raise_error(TE3270::Emulators::InvalidWriteMethodError)
119
+ end
120
+
121
+ it 'should set write_errors_to_ignore to [5, 6] by default' do
122
+ bluezone = TE3270::Emulators::BlueZone.new
123
+ expect(bluezone.instance_variable_get(:@write_errors_to_ignore)).to eq([5, 6])
124
+ end
125
+
126
+ it 'should allow setting write_errors_to_ignore to array of integers' do
127
+ bluezone.connect do |platform|
128
+ platform.write_errors_to_ignore = [6, 7, 8]
129
+ end
130
+ expect(bluezone.instance_variable_get(:@write_errors_to_ignore)).to eq([6, 7, 8])
131
+ end
132
+ end
133
+
134
+ describe "interacting with text fields" do
135
+ it 'should get the value from the screen' do
136
+ expect(bluezone_system).to receive(:PSGetText).with(10, 1532).and_return('blah')
137
+ bluezone.connect
138
+ expect(bluezone.get_string(20, 12, 10)).to eql 'blah'
139
+ end
140
+
141
+ it 'should get the value from the screen if columns were set to 100' do
142
+ expect(bluezone_system).to receive(:PSGetText).with(10, 1912).and_return('blah')
143
+ bluezone.connect do |platform|
144
+ platform.max_column_length = 100
145
+ end
146
+ expect(bluezone.get_string(20, 12, 10)).to eql 'blah'
147
+ end
148
+
149
+ describe "full_string write method" do
150
+ before(:each) do
151
+ bluezone.connect do |platform|
152
+ platform.write_method = :full_string
153
+ end
154
+ end
155
+
156
+ it 'should put the value on the screen' do
157
+ expect(bluezone_system).to receive(:WriteScreen).with('blah', 1, 2)
158
+ expect(bluezone_system).to receive(:WaitReady).with(10, 100).once
159
+ bluezone.connect
160
+ bluezone.put_string('blah', 1, 2)
161
+ end
162
+
163
+ it 'should put the value on the screen with reduced wait delay if overridden' do
164
+ expect(bluezone_system).to receive(:WriteScreen).with('blah', 1, 2)
165
+ expect(bluezone_system).to receive(:WaitReady).with(10, 111).once
166
+ bluezone.connect
167
+ bluezone.max_wait_time = 111
168
+ bluezone.put_string('blah', 1, 2)
169
+ end
170
+
171
+ it 'should cast the value to a string before printing to the screen' do
172
+ expect(bluezone_system).to receive(:WriteScreen).with('1234', 1, 2)
173
+ expect(bluezone_system).to receive(:WaitReady).with(10, 100).once
174
+ bluezone.connect
175
+ bluezone.put_string(1234, 1, 2)
176
+ end
177
+ end
178
+
179
+ describe "char write method" do
180
+ before(:each) do
181
+ bluezone.connect do |platform|
182
+ platform.write_method = :char
183
+ end
184
+ end
185
+
186
+ it 'should put the value on the screen' do
187
+ expect(bluezone_system).to receive(:WriteScreen).with('b', 1, 2).once.and_return(0)
188
+ expect(bluezone_system).to receive(:WriteScreen).with('l', 1, 3).once.and_return(0)
189
+ expect(bluezone_system).to receive(:WriteScreen).with('a', 1, 4).once.and_return(0)
190
+ expect(bluezone_system).to receive(:WriteScreen).with('h', 1, 5).once.and_return(0)
191
+ expect(bluezone_system).to receive(:WaitReady).with(10, 100).exactly(4).times
192
+ bluezone.connect
193
+ bluezone.put_string('blah', 1, 2)
194
+ end
195
+
196
+ it 'should put the value on the screen with reduced wait delay if overridden' do
197
+ expect(bluezone_system).to receive(:WriteScreen).with('b', 1, 2).once.and_return(0)
198
+ expect(bluezone_system).to receive(:WriteScreen).with('l', 1, 3).once.and_return(0)
199
+ expect(bluezone_system).to receive(:WriteScreen).with('a', 1, 4).once.and_return(0)
200
+ expect(bluezone_system).to receive(:WriteScreen).with('h', 1, 5).once.and_return(0)
201
+ expect(bluezone_system).to receive(:WaitReady).with(10, 111).exactly(4).times
202
+ bluezone.connect
203
+ bluezone.max_wait_time = 111
204
+ bluezone.put_string('blah', 1, 2)
205
+ end
206
+
207
+ it 'should put the full string on the screen if allowed error codes returned' do
208
+ expect(bluezone_system).to receive(:WriteScreen).with('b', 1, 2).once.and_return(0)
209
+ expect(bluezone_system).to receive(:WriteScreen).with('l', 1, 3).once.and_return(6)
210
+ expect(bluezone_system).to receive(:WriteScreen).with('a', 1, 4).once.and_return(0)
211
+ expect(bluezone_system).to receive(:WriteScreen).with('h', 1, 5).once.and_return(6)
212
+ expect(bluezone_system).to receive(:WaitReady).with(10, 100).exactly(4).times
213
+ bluezone.connect
214
+ bluezone.put_string('blah', 1, 2)
215
+ end
216
+
217
+ it 'should stop adding characters once an invalid error code is returned' do
218
+ expect(bluezone_system).to receive(:WriteScreen).with('b', 1, 2).once.and_return(4)
219
+ expect(bluezone_system).to receive(:WriteScreen).with('l', 1, 3).once.and_return(5)
220
+ expect(bluezone_system).to receive(:WriteScreen).with('a', 1, 4).once.and_return(10)
221
+ expect(bluezone_system).not_to receive(:WriteScreen).with('h', 1, 5)
222
+ expect(bluezone_system).to receive(:WaitReady).with(10, 100).exactly(2).times
223
+ bluezone.connect do |platform|
224
+ platform.write_errors_to_ignore = [4, 5, 6]
225
+ end
226
+ bluezone.put_string('blah', 1, 2)
227
+ end
228
+
229
+ it 'should cast the value to a string before printing to the screen' do
230
+ expect(bluezone_system).to receive(:WriteScreen).with('1', 1, 2).once.and_return(0)
231
+ expect(bluezone_system).to receive(:WriteScreen).with('2', 1, 3).once.and_return(0)
232
+ expect(bluezone_system).to receive(:WriteScreen).with('3', 1, 4).once.and_return(0)
233
+ expect(bluezone_system).to receive(:WriteScreen).with('4', 1, 5).once.and_return(0)
234
+ expect(bluezone_system).to receive(:WaitReady).with(10, 100).exactly(4).times
235
+ bluezone.connect
236
+ bluezone.put_string(1234, 1, 2)
237
+ end
238
+ end
239
+ end
240
+
241
+ describe "interacting with the screen" do
242
+ it 'should know how to send function keys' do
243
+ expect(bluezone_system).to receive(:SendKey).with('<Clear>')
244
+ expect(bluezone_system).to receive(:WaitReady).with(10, 100)
245
+ bluezone.connect
246
+ bluezone.send_keys(TE3270.Clear)
247
+ end
248
+
249
+ it 'should know how to send function keys with reduced wait delay if overridden' do
250
+ expect(bluezone_system).to receive(:SendKey).with('<Clear>')
251
+ expect(bluezone_system).to receive(:WaitReady).with(10, 111)
252
+ bluezone.connect
253
+ bluezone.max_wait_time = 111
254
+ bluezone.send_keys(TE3270.Clear)
255
+ end
256
+
257
+ it 'should wait for a string to appear' do
258
+ expect(bluezone_system).to receive(:WaitForText).with('The String', 3, 10, 10).and_return(0)
259
+ bluezone.connect
260
+ bluezone.wait_for_string('The String', 3, 10)
261
+ end
262
+
263
+ it 'should respect custom timeout for a string to appear' do
264
+ expect(bluezone_system).to receive(:WaitForText).with('The String', 3, 10, 24).and_return(0)
265
+ bluezone.connect
266
+ bluezone.timeout = 24
267
+ bluezone.wait_for_string('The String', 3, 10)
268
+ end
269
+
270
+ it 'should wait for the host to be quiet' do
271
+ expect(bluezone_system).to receive(:Wait).with(4)
272
+ bluezone.connect
273
+ bluezone.wait_for_host(4)
274
+ end
275
+
276
+ it 'should wait until the cursor is at a position' do
277
+ expect(bluezone_system).to receive(:WaitCursor).with(10, 5, 8, 3).and_return(0)
278
+ bluezone.connect
279
+ bluezone.wait_until_cursor_at(5, 8)
280
+ end
281
+
282
+ it 'should respect custom timeout while waiting until the cursor is at a position' do
283
+ expect(bluezone_system).to receive(:WaitCursor).with(24, 5, 8, 3).and_return(0)
284
+ bluezone.connect
285
+ bluezone.timeout = 24
286
+ bluezone.wait_until_cursor_at(5, 8)
287
+ end
288
+
289
+ it "should get the screen text" do
290
+ expect(bluezone_system).to receive(:PSText).and_return('blah')
291
+ bluezone.connect
292
+ expect(bluezone.text).to eql 'blah'
293
+ end
294
+
295
+ if Gem.win_platform?
296
+ it 'should take screenshots' do
297
+ take = double('Take')
298
+ expect(bluezone_system).to receive(:WindowHandle).and_return(123)
299
+ expect(Win32::Screenshot::Take).to receive(:of).with(:window, hwnd: 123).and_return(take)
300
+ expect(take).to receive(:write).with('image.png')
301
+ bluezone.connect
302
+ bluezone.screenshot('image.png')
303
+ end
304
+
305
+ it 'should make the window visible before taking a screenshot' do
306
+ take = double('Take')
307
+ expect(bluezone_system).to receive(:WindowHandle).and_return(123)
308
+ expect(Win32::Screenshot::Take).to receive(:of).with(:window, hwnd: 123).and_return(take)
309
+ expect(take).to receive(:write).with('image.png')
310
+ expect(bluezone_window).to receive(:Visible=).twice.with(true)
311
+ expect(bluezone_window).to receive(:Visible=).twice.with(false)
312
+ bluezone.connect do |emulator|
313
+ emulator.visible = false
314
+ end
315
+ bluezone.screenshot('image.png')
316
+ end
317
+
318
+ it 'should delete the file for the screenshot if it already exists' do
319
+ expect(File).to receive(:exists?).and_return(true)
320
+ expect(File).to receive(:delete)
321
+ take = double('Take')
322
+ expect(bluezone_system).to receive(:WindowHandle).and_return(123)
323
+ expect(Win32::Screenshot::Take).to receive(:of).with(:window, hwnd: 123).and_return(take)
324
+ expect(take).to receive(:write).with('image.png')
325
+ bluezone.connect
326
+ bluezone.screenshot('image.png')
327
+ end
328
+ end
329
+ end
330
+ end
@@ -84,13 +84,13 @@ describe TE3270 do
84
84
  if Gem.win_platform?
85
85
  it 'should accept a block when creating an emulator' do
86
86
  expect(WIN32OLE).to receive(:new).and_return(extra_system)
87
- expect(extra_session).to receive(:Open).with('blah.edp').and_return(extra_session)
87
+ expect(extra_system.Sessions).to receive(:Open).with('blah.edp').and_return(extra_session)
88
88
  TE3270.emulator_for :extra do |emulator|
89
89
  emulator.session_file = 'blah.edp'
90
90
  end
91
91
  end
92
92
  end
93
-
93
+
94
94
  it 'should allow one to disconnect using the module' do
95
95
  expect(platform).to receive(:disconnect)
96
96
  TE3270.disconnect(platform)
@@ -7,6 +7,20 @@ if Gem.win_platform?
7
7
  require 'win32/screenshot'
8
8
  end
9
9
 
10
+ def bluezone_system
11
+ @bluezone_system ||= double('system')
12
+ allow(@bluezone_system).to receive(:Connect).and_return(0)
13
+ allow(@bluezone_system).to receive(:OpenSession).and_return(0)
14
+ allow(@bluezone_system).to receive(:Window).and_return(bluezone_window)
15
+ allow(@bluezone_system).to receive(:WindowState=)
16
+ @bluezone_system
17
+ end
18
+
19
+ def bluezone_window
20
+ @bluezone_window ||= double('window')
21
+ allow(@bluezone_window).to receive(:Visible=)
22
+ @bluezone_window
23
+ end
10
24
 
11
25
  def extra_system
12
26
  @extra_system ||= double('system')
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.add_dependency 'watir', '~> 6.0'
25
25
  spec.add_dependency 'win32screenshot' if Gem.win_platform?
26
26
 
27
- spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "bundler"
28
28
  spec.add_development_dependency "rake"
29
29
  spec.add_development_dependency "rspec"
30
30
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: te3270
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeffrey S. Morgan
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2017-03-06 00:00:00.000000000 Z
16
+ date: 2020-03-19 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: page_navigation
@@ -47,16 +47,16 @@ dependencies:
47
47
  name: bundler
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  requirements:
50
- - - "~>"
50
+ - - ">="
51
51
  - !ruby/object:Gem::Version
52
- version: '1.3'
52
+ version: '0'
53
53
  type: :development
54
54
  prerelease: false
55
55
  version_requirements: !ruby/object:Gem::Requirement
56
56
  requirements:
57
- - - "~>"
57
+ - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: '1.3'
59
+ version: '0'
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: rake
62
62
  requirement: !ruby/object:Gem::Requirement
@@ -111,6 +111,7 @@ files:
111
111
  - lib/te3270.rb
112
112
  - lib/te3270/accessors.rb
113
113
  - lib/te3270/emulator_factory.rb
114
+ - lib/te3270/emulators/bluezone.rb
114
115
  - lib/te3270/emulators/extra.rb
115
116
  - lib/te3270/emulators/quick3270.rb
116
117
  - lib/te3270/emulators/virtel.rb
@@ -120,6 +121,7 @@ files:
120
121
  - lib/te3270/screen_populator.rb
121
122
  - lib/te3270/version.rb
122
123
  - spec/lib/te3270/accessors_spec.rb
124
+ - spec/lib/te3270/emulators/bluezone_spec.rb
123
125
  - spec/lib/te3270/emulators/extra_spec.rb
124
126
  - spec/lib/te3270/emulators/quick3270_spec.rb
125
127
  - spec/lib/te3270/emulators/x3270_spec.rb
@@ -147,13 +149,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
149
  - !ruby/object:Gem::Version
148
150
  version: '0'
149
151
  requirements: []
150
- rubyforge_project:
151
- rubygems_version: 2.5.2
152
+ rubygems_version: 3.0.1
152
153
  signing_key:
153
154
  specification_version: 4
154
155
  summary: Automates a 3270 Terminal Emulator
155
156
  test_files:
156
157
  - spec/lib/te3270/accessors_spec.rb
158
+ - spec/lib/te3270/emulators/bluezone_spec.rb
157
159
  - spec/lib/te3270/emulators/extra_spec.rb
158
160
  - spec/lib/te3270/emulators/quick3270_spec.rb
159
161
  - spec/lib/te3270/emulators/x3270_spec.rb