te3270 0.1-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,49 @@
1
+ require 'page_navigation'
2
+
3
+ module TE3270
4
+ #
5
+ # Module to facilitate to creating of screen objects in step definitions. You
6
+ # can make the methods below available to all of your step definitions by adding
7
+ # this module to World.
8
+ #
9
+ # @example Making the ScreenFactory available to your step definitions
10
+ # World TE3270::ScreenFactory
11
+ #
12
+ # @example using a screen in a Scenario
13
+ # on MyScreen do |screen|
14
+ # screen.name = 'Cheezy'
15
+ # end
16
+ #
17
+ # If you plan to use the +navigate_to+ method you will need to ensure
18
+ # you setup the possible routes ahead of time. You must always have
19
+ # a default route in order for this to work. Here is an example of
20
+ # how you define routes:
21
+ #
22
+ # @example Example routes defined in env.rb
23
+ # TE3270::ScreenFactory.routes = {
24
+ # :default => [[ScreenOne,:method1], [ScreenTwo,:method2], [ScreenThree,:method3]],
25
+ # :another_route => [[ScreenOne,:method1, "arg1"], [ScreenTwo,:method2b], [ScreenThree,:method3]]
26
+ # }
27
+ #
28
+ # Notice the first entry of :another_route is passing an argument
29
+ # to the method.
30
+ #
31
+ module ScreenFactory
32
+ include PageNavigation
33
+
34
+ #
35
+ # Create a screen object. Also sets an instance variable +@current_screen
36
+ #
37
+ # @param [Class] screen_class a class that has included the TE3270 module
38
+ # @param [block] an optional block to be called
39
+ # @return [ScreenObject] the newly created screen object
40
+ #
41
+ def on(screen_class, &block)
42
+ raise '@emulator instance variable must be available to use the ScreenFactory methods' unless @emulator
43
+ @current_screen = screen_class.new @emulator
44
+ block.call @current_screen if block
45
+ @current_screen
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,4 @@
1
+ module TE3270
2
+ VERSION = "0.1"
3
+ end
4
+
data/lib/te3270.rb ADDED
@@ -0,0 +1,166 @@
1
+ require 'te3270/version'
2
+ require 'te3270/accessors'
3
+ require 'te3270/screen_factory'
4
+ require 'te3270/function_keys'
5
+ require 'te3270/emulator_factory'
6
+ require 'te3270/emulators/extra'
7
+ require 'te3270/emulators/quick3270'
8
+
9
+ #
10
+ # This gem can be used to drive a 3270 terminal emulator. You have to have a supported emulator installed on the
11
+ # machines on which you use the gem. Currently the only supported emulators are EXTRA! X-treme by Attachmate and
12
+ # Quick3270 by DN-Computing. These are commercial products and you will need to purchase one of them in order to
13
+ # use this gem. We do plan to support other emulators as time permits.
14
+ #
15
+ # This gem has been designed to work very similar to the page-object gem. You will use it to create screen objects
16
+ # for each screen in your application. Here is an example of one and how it can be used:
17
+ #
18
+ # @example Example mainframe page
19
+ # class MainframeScreen
20
+ # include TE3270
21
+ #
22
+ # text_field(:userid, 10, 30, 20, true)
23
+ # text_field(:password, 12, 30, 20, true)
24
+ # end
25
+ #
26
+ # ...
27
+ #
28
+ # emulator = TN3270.emulator_for :extra do |emulator|
29
+ # emulator.session_file = 'path_to_session_file'
30
+ # end
31
+ # my_screen = MainframeScreen.new(emulator)
32
+ # my_screen.userid = 'the_id'
33
+ # my_screen.password = 'the_password'
34
+ #
35
+ # Another option is to mixin the +TE3270::ScreenFactory+ module on use the factory methods to create the screen
36
+ # objects. If you are using Cucumber you can do this by calling the +World+ method in your env.rb file. Then
37
+ # you can use the factory and navigation methods in your step definitions.
38
+ #
39
+ # @example Registering the ScreenFactory with Cucumber World
40
+ # World(TE3270::ScreenFactory)
41
+ #
42
+ # Before do
43
+ # @emulator = TE3270.emulator_for :quick3270 do |emulator|
44
+ # emulator.session_file = 'path_to_session_file'
45
+ # end
46
+ # end
47
+ #
48
+ #
49
+ # @example Using the factory method in a step definition
50
+ # on(MainframeScreen).do_something
51
+ #
52
+ #
53
+ # @see #TE3270::ScreenFactory for more details on using the factory and navigation methods
54
+ #
55
+ module TE3270
56
+ extend FunctionKeys
57
+
58
+ def self.included(cls)
59
+ cls.extend TE3270::Accessors
60
+ end
61
+
62
+ #
63
+ # Starts the terminal emulator and makes the connection. This method requires a block
64
+ # that has emulator specific information that is necessary to complete the connection.
65
+ # To know what information you should provide in the block please see the classes in
66
+ # the TE3270::Emulators package.
67
+ #
68
+ #@param platform =[:extra,:quick3270] use :extra for Extra emulator and :quick3270 for quick emulator
69
+ #
70
+ def self.emulator_for(platform, &block)
71
+ platform_class = TE3270::EmulatorFactory.emulator_for(platform)
72
+ @platform = platform_class.new
73
+ @platform.connect &block
74
+ @platform
75
+ end
76
+
77
+ #
78
+ # Disconnects and closes the emulator
79
+ #
80
+ def self.disconnect(emulator)
81
+ emulator.disconnect
82
+ end
83
+
84
+ def initialize(platform)
85
+ @platform = platform
86
+ initialize_screen if respond_to? :initialize_screen
87
+ end
88
+
89
+ #
90
+ # Open a new screen and connect to the host. Platform specific values are set by
91
+ # passing a block to this method. To see the valid platform specific values please
92
+ # read the documentation for your emulator class in the TE3270::Emulators module.
93
+ #
94
+ def connect
95
+ platform.connect
96
+ end
97
+
98
+ #
99
+ # Disconnect from platform (extra or quick)
100
+ #
101
+ def disconnect
102
+ platform.disconnect
103
+ end
104
+
105
+ #
106
+ # Send keys on the emulator
107
+ #
108
+ def send_keys(keys)
109
+ platform.send_keys(keys)
110
+ end
111
+
112
+ #
113
+ # Retrieves the text from the current screen
114
+ #
115
+ def text
116
+ platform.text
117
+ end
118
+
119
+ #
120
+ # Takes screenshot and saves to the filename specified. If you have visibility set to false
121
+ # then this method will first of all make the screen visible, take the screenshot, and then
122
+ # make set visibility to false again.
123
+ #
124
+ # @param [String] filename of the file to be saved.
125
+ #
126
+ def screenshot(filename)
127
+ platform.screenshot(filename)
128
+ end
129
+
130
+ #
131
+ # Waits for the string to appear at the specified location
132
+ #
133
+ # @param [String] String to wait for
134
+ # @param [FixedNum] row number
135
+ # @param [FixedNum] column number
136
+ #
137
+ def wait_for_string(str, row, column)
138
+ platform.wait_for_string(str, row, column)
139
+ end
140
+
141
+ #
142
+ # Waits for the host for specified # of seconds. Default is 5 seconds
143
+ #
144
+ # @param [FixedNum] seconds to wait for
145
+ #
146
+ def wait_for_host(seconds=5)
147
+ platform.wait_for_host(seconds)
148
+ end
149
+
150
+ #
151
+ # Waits for the cursor to appear at the specified location
152
+ #
153
+ # @param [FixedNum] row number
154
+ # @param [FixedNum] column number
155
+ #
156
+ def wait_until_cursor_at(row, column)
157
+ platform.wait_until_cursor_at(row, column)
158
+ end
159
+
160
+ private
161
+
162
+ def platform
163
+ @platform ||= Extra.new
164
+ end
165
+
166
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ class AccessorsTestScreen
4
+ include TE3270
5
+
6
+ text_field(:method_name, 1, 2, 10, true)
7
+ text_field(:read_only, 2, 3, 12, false)
8
+ text_field(:default_editable, 3, 4, 14)
9
+ end
10
+
11
+ describe TE3270::Accessors do
12
+
13
+ let(:platform) { double('platform') }
14
+ let(:screen_object) { AccessorsTestScreen.new platform }
15
+
16
+ before(:each) do
17
+ screen_object.stub(:platform).and_return platform
18
+ end
19
+
20
+ describe "text_field accessors" do
21
+
22
+ it 'should generate a method to retrieve the value' do
23
+ screen_object.should respond_to :method_name
24
+ end
25
+
26
+ it 'should generate a method to set the value' do
27
+ screen_object.should respond_to :method_name=
28
+ end
29
+
30
+ it 'should not generate a method to set the value if it is not editable' do
31
+ screen_object.should_not respond_to :read_only=
32
+ end
33
+
34
+ it 'should default to being editable when it is not specified' do
35
+ screen_object.should respond_to :default_editable=
36
+ end
37
+
38
+ it 'should use the platform to get the text value' do
39
+ platform.should_receive(:get_string).with(1, 2, 10).and_return('abc')
40
+ screen_object.method_name.should == 'abc'
41
+ end
42
+
43
+ it 'should use the platform to set the text value' do
44
+ platform.should_receive(:put_string).with('abc', 1, 2)
45
+ screen_object.method_name = 'abc'
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,182 @@
1
+ require 'spec_helper'
2
+
3
+ describe TE3270::Emulators::Extra do
4
+
5
+ let(:extra) { TE3270::Emulators::Extra.new }
6
+
7
+ before(:each) do
8
+ WIN32OLE.stub(:new).and_return extra_system
9
+ extra.instance_variable_set(:@session_file, 'the_file')
10
+ File.stub(:exists).and_return false
11
+ end
12
+
13
+
14
+ describe "global behaviors" do
15
+ it 'should start a new terminal' do
16
+ WIN32OLE.should_receive(:new).and_return(extra_system)
17
+ extra.connect
18
+ end
19
+
20
+ it 'should open a session' do
21
+ extra_sessions.should_receive(:Open).and_return(extra_session)
22
+ extra.connect
23
+ end
24
+
25
+ it 'should not display the splash screen if version is higher than 9' do
26
+ extra_system.should_receive(:Version).and_return("9.2")
27
+ extra_sessions.should_receive(:VisibleOnStartup=).with(true)
28
+ extra.connect
29
+ end
30
+
31
+ it 'should call a block allowing the session file to be set' do
32
+ extra_sessions.should_receive(:Open).with('blah.edp').and_return(extra_session)
33
+ extra.connect do |platform|
34
+ platform.session_file = 'blah.edp'
35
+ end
36
+ end
37
+
38
+ it 'should raise an error when the session file is not set' do
39
+ extra.instance_variable_set(:@session_file, nil)
40
+ expect { extra.connect }.to raise_error('The session file must be set in a block when calling connect with the Extra emulator.')
41
+ end
42
+
43
+ it 'should take the visible value from a block' do
44
+ extra_session.should_receive(:Visible=).with(false)
45
+ extra.connect do |platform|
46
+ platform.visible = false
47
+ end
48
+ end
49
+
50
+ it 'should default to visible when not specified' do
51
+ extra_session.should_receive(:Visible=).with(true)
52
+ extra.connect
53
+ end
54
+
55
+ it 'should take the window state value from the block' do
56
+ extra_session.should_receive(:WindowState=).with(2)
57
+ extra.connect do |platform|
58
+ platform.window_state = :maximized
59
+ end
60
+ end
61
+
62
+ it 'should default to window state normal when not specified' do
63
+ extra_session.should_receive(:WindowState=).with(1)
64
+ extra.connect
65
+ end
66
+
67
+ it 'should default to being visible' do
68
+ extra_session.should_receive(:Visible=).with(true)
69
+ extra.connect
70
+ end
71
+
72
+ it 'should get the screen for the active session' do
73
+ extra_session.should_receive(:Screen).and_return(extra_screen)
74
+ extra.connect
75
+ end
76
+
77
+ it 'should get the area from the screen' do
78
+ extra_screen.should_receive(:SelectAll).and_return(extra_area)
79
+ extra.connect
80
+ end
81
+
82
+ it 'should disconnect from a session' do
83
+ extra_system.should_receive(:Quit)
84
+ extra.connect
85
+ extra.disconnect
86
+ end
87
+ end
88
+
89
+ describe "interacting with text fields" do
90
+ it 'should get the value from the screen' do
91
+ extra_screen.should_receive(:GetString).with(1, 2, 10).and_return('blah')
92
+ extra.connect
93
+ extra.get_string(1, 2, 10).should == 'blah'
94
+ end
95
+
96
+ it 'should put the value on the screen' do
97
+ wait_collection = double('wait')
98
+ extra_screen.should_receive(:PutString).with('blah', 1, 2)
99
+ extra_screen.should_receive(:WaitHostQuiet).and_return(wait_collection)
100
+ wait_collection.should_receive(:Wait).with(1000)
101
+ extra.connect
102
+ extra.put_string('blah', 1, 2)
103
+ end
104
+ end
105
+
106
+ describe "interacting with the screen" do
107
+ it 'should know how to send function keys' do
108
+ wait_collection = double('wait')
109
+ extra_screen.should_receive(:SendKeys).with('<Clear>')
110
+ extra_screen.should_receive(:WaitHostQuiet).and_return(wait_collection)
111
+ wait_collection.should_receive(:Wait).with(1000)
112
+ extra.connect
113
+ extra.send_keys(TE3270.Clear)
114
+ end
115
+
116
+ it 'should wait for a string to appear' do
117
+ wait_col = double('wait')
118
+ extra_screen.should_receive(:WaitForString).with('The String', 3, 10).and_return(wait_col)
119
+ extra_system.should_receive(:TimeoutValue).and_return(30000)
120
+ wait_col.should_receive(:Wait).with(30000)
121
+ extra.connect
122
+ extra.wait_for_string('The String', 3, 10)
123
+ end
124
+
125
+ it 'should wait for the host to be quiet' do
126
+ wait_col = double('wait')
127
+ extra_screen.should_receive(:WaitHostQuiet).and_return(wait_col)
128
+ wait_col.should_receive(:Wait).with(4000)
129
+ extra.connect
130
+ extra.wait_for_host(4)
131
+ end
132
+
133
+ it 'should wait until the cursor is at a position' do
134
+ wait_col = double('wait')
135
+ extra_screen.should_receive(:WaitForCursor).with(5, 8).and_return(wait_col)
136
+ extra_system.should_receive(:TimeoutValue).and_return(30000)
137
+ wait_col.should_receive(:Wait).with(30000)
138
+ extra.connect
139
+ extra.wait_until_cursor_at(5, 8)
140
+ end
141
+
142
+ it 'should take screenshots' do
143
+ take = double('Take')
144
+ extra_session.should_receive(:WindowHandle).and_return(123)
145
+ Win32::Screenshot::Take.should_receive(:of).with(:window, hwnd: 123).and_return(take)
146
+ take.should_receive(:write).with('image.png')
147
+ extra.connect
148
+ extra.screenshot('image.png')
149
+ end
150
+
151
+ it 'should make the window visible before taking a screenshot' do
152
+ take = double('Take')
153
+ extra_session.should_receive(:WindowHandle).and_return(123)
154
+ Win32::Screenshot::Take.should_receive(:of).with(:window, hwnd: 123).and_return(take)
155
+ take.should_receive(:write).with('image.png')
156
+ extra_session.should_receive(:Visible=).once.with(true)
157
+ extra_session.should_receive(:Visible=).twice.with(false)
158
+ extra.connect do |emulator|
159
+ emulator.visible = false
160
+ end
161
+ extra.screenshot('image.png')
162
+ end
163
+
164
+ it 'should delete the file for the screenshot if it already exists' do
165
+ File.should_receive(:exists?).and_return(true)
166
+ File.should_receive(:delete)
167
+ take = double('Take')
168
+ extra_session.should_receive(:WindowHandle).and_return(123)
169
+ Win32::Screenshot::Take.should_receive(:of).with(:window, hwnd: 123).and_return(take)
170
+ take.should_receive(:write).with('image.png')
171
+ extra.connect
172
+ extra.screenshot('image.png')
173
+ end
174
+
175
+ it "should get the screen text" do
176
+ extra_area.should_receive(:Value).and_return('blah')
177
+ extra.connect
178
+ extra.text.should == 'blah'
179
+ end
180
+
181
+ end
182
+ end
@@ -0,0 +1,166 @@
1
+ require 'spec_helper'
2
+
3
+ describe TE3270::Emulators::Quick3270 do
4
+
5
+ let(:quick) { TE3270::Emulators::Quick3270.new }
6
+
7
+ before(:each) do
8
+ WIN32OLE.stub(:new).and_return quick_system
9
+ quick.instance_variable_set(:@session_file, 'the_host')
10
+ end
11
+
12
+ describe "global behaviors" do
13
+ it 'should start new terminal' do
14
+ WIN32OLE.should_receive(:new).and_return(quick_system)
15
+ quick.connect
16
+ end
17
+
18
+ it 'should establish a session' do
19
+ quick_system.should_receive(:ActiveSession).and_return(quick_session)
20
+ quick.connect
21
+ end
22
+
23
+ it 'should get the screen from the active session' do
24
+ quick_session.should_receive(:Screen).and_return(quick_screen)
25
+ quick.connect
26
+ end
27
+
28
+ it 'should take the Visible value from a block' do
29
+ quick_system.should_receive(:Visible=).with(false)
30
+ quick.connect do |platform|
31
+ platform.visible = false
32
+ end
33
+ end
34
+
35
+ it 'should take the session file from a block' do
36
+ quick.should_receive(:session_file=).with('blah.txt')
37
+ quick.connect do |platform|
38
+ platform.session_file = 'blah.txt'
39
+ end
40
+ end
41
+
42
+ it 'should display an error when the session file is not set' do
43
+ quick.instance_variable_set(:@session_file, nil)
44
+ expect { quick.connect }.to raise_error('The session file must be set in a block when calling connect with the Quick3270 emulator.')
45
+ end
46
+
47
+ it 'should open the connection using the sesion file' do
48
+ quick_session.should_receive(:Open).with('blah.txt')
49
+ quick.connect do |platform|
50
+ platform.session_file = 'blah.txt'
51
+ end
52
+ end
53
+
54
+ it 'should default to Visible being true when not provided' do
55
+ quick_system.should_receive(:Visible=).with(true)
56
+ quick.connect
57
+ end
58
+
59
+ it 'should make the connection via the session' do
60
+ quick_session.should_receive(:Connect)
61
+ quick.connect
62
+ end
63
+
64
+ it 'should check to make sure the connection is successful before continuing' do
65
+ quick_session.should_receive(:Connected).once.and_return(false)
66
+ quick_screen.should_receive(:WaitHostQuiet).once.with(1000)
67
+ quick_session.should_receive(:Connected).once.and_return(true)
68
+ quick.connect
69
+ end
70
+
71
+ it 'should disconnect from a session' do
72
+ application = double('application')
73
+ quick_session.should_receive(:Disconnect)
74
+ quick_system.should_receive(:Application).and_return(application)
75
+ application.should_receive(:Quit)
76
+ quick.connect
77
+ quick.disconnect
78
+ end
79
+ end
80
+
81
+ describe "interacting with text fields" do
82
+ it 'should get the value from the screen' do
83
+ quick_screen.should_receive(:GetString).with(1, 2, 7).and_return('blah')
84
+ quick.connect
85
+ quick.get_string(1, 2, 7).should == 'blah'
86
+ end
87
+
88
+ it 'should put a value on the screen' do
89
+ quick_screen.should_receive(:MoveTo).with(15, 56)
90
+ quick_screen.should_receive(:PutString).with('blah')
91
+ quick_screen.should_receive(:WaitHostQuiet).with(3000)
92
+ quick.connect
93
+ quick.put_string('blah', 15, 56)
94
+ end
95
+ end
96
+
97
+ describe "interacting with the screen" do
98
+ it 'should know how to send function keys' do
99
+ quick_screen.should_receive(:SendKeys).with('<Home>')
100
+ quick_screen.should_receive(:WaitHostQuiet).with(3000)
101
+ quick.connect
102
+ quick.send_keys(TE3270.Home)
103
+ end
104
+
105
+ it 'should wait for a string to appear' do
106
+ quick_screen.should_receive(:WaitForString).with('string', 3, 10)
107
+ quick.connect
108
+ quick.wait_for_string('string', 3, 10)
109
+ end
110
+
111
+ it 'should wait for the host to be quiet' do
112
+ quick_screen.should_receive(:WaitHostQuiet).with(6000)
113
+ quick.connect
114
+ quick.wait_for_host(6)
115
+ end
116
+
117
+ it 'should wait until the cursor is at a position' do
118
+ quick_screen.should_receive(:WaitForCursor).with(5, 8)
119
+ quick.connect
120
+ quick.wait_until_cursor_at(5,8)
121
+ end
122
+
123
+ it 'should take screenshots' do
124
+ take = double('Take')
125
+ quick_system.should_receive(:WindowTitle).and_return('The Title')
126
+ Win32::Screenshot::Take.should_receive(:of).with(:window, title: 'The Title').and_return(take)
127
+ take.should_receive(:write).with('image.png')
128
+ quick.connect
129
+ quick.screenshot('image.png')
130
+ end
131
+
132
+ it 'should delete the file for the screenshot if it already exists' do
133
+ File.should_receive(:exists?).and_return(true)
134
+ File.should_receive(:delete)
135
+ take = double('Take')
136
+ quick_system.should_receive(:WindowTitle).and_return('The Title')
137
+ Win32::Screenshot::Take.should_receive(:of).with(:window, title: 'The Title').and_return(take)
138
+ take.should_receive(:write).with('image.png')
139
+ quick.connect
140
+ quick.screenshot('image.png')
141
+ end
142
+
143
+ it 'should make the window visible before taking a screenshot' do
144
+ take = double('Take')
145
+ quick_system.should_receive(:WindowTitle).and_return('The Title')
146
+ Win32::Screenshot::Take.should_receive(:of).with(:window, title: 'The Title').and_return(take)
147
+ take.should_receive(:write).with('image.png')
148
+ quick_system.should_receive(:Visible=).once.with(true)
149
+ quick_system.should_receive(:Visible=).twice.with(false)
150
+ quick.connect do |emulator|
151
+ emulator.visible = false
152
+ end
153
+ quick.screenshot('image.png')
154
+ end
155
+
156
+ it 'should get the screen text' do
157
+ quick_screen.should_receive(:Rows).and_return(3)
158
+ quick_screen.should_receive(:Cols).and_return(10)
159
+ 3.times do |time|
160
+ quick_screen.should_receive(:GetString).with(time+1, 1, 10).and_return("row #{time}")
161
+ end
162
+ quick.connect
163
+ quick.text.should == 'row 0\nrow 1\nrow 2\n'
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ class ScreenFactoryScreen
4
+ include TE3270
5
+ end
6
+
7
+ class World
8
+ include TE3270::ScreenFactory
9
+ end
10
+
11
+ describe TE3270::ScreenFactory do
12
+
13
+ let(:world) { World.new }
14
+
15
+ it 'should create a new screen object' do
16
+ emulator = double('platform')
17
+ world.instance_variable_set('@emulator', emulator)
18
+ world.on(ScreenFactoryScreen).should be_instance_of ScreenFactoryScreen
19
+ end
20
+
21
+ it 'should create a new screen object and execute a block' do
22
+ emulator = double('platform')
23
+ world.instance_variable_set('@emulator', emulator)
24
+ world.on(ScreenFactoryScreen) do |page|
25
+ page.should be_instance_of ScreenFactoryScreen
26
+ end
27
+ end
28
+
29
+ it 'should raise an error when an @emulator instance variable does not exist' do
30
+ expect { world.on(ScreenFactoryScreen) }.to raise_error("@emulator instance variable must be available to use the ScreenFactory methods")
31
+ end
32
+ end