-
Notifications
You must be signed in to change notification settings - Fork 2
/
ServerOnly_Steps.as
239 lines (195 loc) · 9.82 KB
/
ServerOnly_Steps.as
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/**
* Copyright (c) 2011 FlashQuartermaster Ltd
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* @author Tom Coxen
* @version
**/
package features.step_definitions
{
import com.adobe.serialization.json.JSON;
import com.flashquartermaster.cuke4as3.Config;
import com.flashquartermaster.cuke4as3.net.BinarySwfLoader;
import com.flashquartermaster.cuke4as3.net.CommandProcessor;
import com.flashquartermaster.cuke4as3.net.Cuke4AS3Server;
import com.flashquartermaster.cuke4as3.reflection.IStepInvoker;
import com.flashquartermaster.cuke4as3.reflection.StepInvoker;
import com.flashquartermaster.cuke4as3.reflection.StepMatcher;
import com.flashquartermaster.cuke4as3.reflection.SwfProcessor;
import com.flashquartermaster.cuke4as3.utilities.StepsBase;
import com.flashquartermaster.cuke4as3.utilities.Table;
import flash.events.ErrorEvent;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.ServerSocketConnectEvent;
import flash.net.Socket;
import flash.system.ApplicationDomain;
import org.flexunit.async.Async;
import org.hamcrest.assertThat;
import org.hamcrest.collection.array;
import org.hamcrest.collection.arrayWithSize;
import org.hamcrest.core.allOf;
import org.hamcrest.object.equalTo;
import org.hamcrest.object.hasPropertyWithValue;
import support.FileHelper;
public class ServerOnly_Steps extends StepsBase
{
private var _fileHelper:FileHelper;
private var _mockPackageName:String = "features.step_definitions";
private var _mockClassName:String = "Mock_Steps";
// This step is the 'when' step generated by the ClassMaker that is used by the file helper to generate a swf on the fly
private var _stepToMatch:String = "I do something with " + _argValue;
private var _stepRegExp:String = "I do something with (\\d+)";
private var _argValue:int = 50;
private var _binarySwfLoader:BinarySwfLoader;
private var _stepInvoker:IStepInvoker;
private var _stepMatcher:StepMatcher;
private var _swfProcessor:SwfProcessor;
private var _cuke4AS3Server:Cuke4AS3Server;
private var _mockCucumber:Socket;
public function ServerOnly_Steps()
{
}
[Given(/^a valid swf is loaded$/, "async")]
public function should_be_valid_loaded_swf():void
{
_binarySwfLoader = new BinarySwfLoader();
_binarySwfLoader.init();
_fileHelper = new FileHelper();
// Please note: This makes a class at runtime and writes the bytes to a tmp swf file that we load in
_binarySwfLoader.swfToLoad = "file://" + _fileHelper.getValidSwfPath( Config.OUTPUT_SWF, _mockPackageName, _mockClassName );
Async.proceedOnEvent( this, _binarySwfLoader, Event.COMPLETE );
Async.failOnEvent( this, _binarySwfLoader, ErrorEvent.ERROR );
_binarySwfLoader.load();
}
[Given(/^the loaded swf is processed successfully$/, "async")]
public function should_successfully_process_swf():void
{
//TODO: Tidy up the step matcher and step invoker api's
// Having loaded the swf, process the classes in the correct application domain
var applicationDomain:ApplicationDomain = _binarySwfLoader.applicationDomain;
// Step invoker gets the code out of the application domain
_stepInvoker = new StepInvoker();
_stepInvoker.applicationDomain = applicationDomain;
// Step matcher sets the invokable steps on the step invoker on the fly
_stepMatcher = new StepMatcher( _stepInvoker );
// The swf processor processes classes in a specific application domain
_swfProcessor = new SwfProcessor();
_swfProcessor.applicationDomain = applicationDomain;
// The swf processor sets matchable steps on the step matcher based on its analysis
_swfProcessor.stepMatcher = _stepMatcher;
_swfProcessor.stepDirectoryFiles = _fileHelper.getStepsDir( [_mockClassName] );
Async.proceedOnEvent( this, _swfProcessor, Event.COMPLETE );
Async.failOnEvent( this, _swfProcessor, ErrorEvent.ERROR );
_swfProcessor.processLoadedClasses();
}
[When(/^I run the wire server on:$/, "async")]
public function should_run_the_wire_server( array:Array ):void
{
var table:Table = new Table( array );
_cuke4AS3Server = new Cuke4AS3Server();
_cuke4AS3Server.host = table.getRowItemByHeader( "host", 0 );
_cuke4AS3Server.port = int( table.getRowItemByHeader( "port", 0 ) );
var commandProcessor:CommandProcessor = new CommandProcessor();
commandProcessor.stepInvoker = _stepInvoker;
commandProcessor.stepMatcher = _stepMatcher;
_cuke4AS3Server.commandProcessor = commandProcessor;
Async.proceedOnEvent( this, _cuke4AS3Server, Event.INIT );
Async.failOnEvent( this, _cuke4AS3Server, ErrorEvent.ERROR );
_cuke4AS3Server.run();
}
[When(/^cucumber connects to it$/, "async")]
public function cucumber_should_connect():void
{
_mockCucumber = new Socket();
Async.proceedOnEvent( this, _cuke4AS3Server.server, ServerSocketConnectEvent.CONNECT );
_mockCucumber.connect( _cuke4AS3Server.host, _cuke4AS3Server.port );
}
[Then(/^I can match a step definition$/, "async")]
public function should_match_a_step_definition():void
{
Async.handleEvent( this, _mockCucumber, ProgressEvent.SOCKET_DATA, onMatchResponse, 5 * 1000 );
_mockCucumber.writeUTFBytes( "[\"step_matches\",{\"name_to_match\":\"" + _stepToMatch + "\"}]\n" );
_mockCucumber.flush();
}
[Then(/^I can invoke the code related to it$/, "async")]
public function should_invoke_the_code_related_to_it():void
{
Async.handleEvent( this, _mockCucumber, ProgressEvent.SOCKET_DATA, onInvokeResponse, 5 * 1000 );
_mockCucumber.writeUTFBytes( "[\"invoke\",{\"args\":[" + _argValue + "],\"id\":0}]\n" );
_mockCucumber.flush();
}
[Then(/^I know when cucumber has finished using me$/, "async")]
public function cucumber_should_disconnect_when_done():void
{
//This indicates the end of the process
Async.proceedOnEvent( this, _cuke4AS3Server, Event.COMPLETE );
_mockCucumber.close();
}
override public function destroy():void
{
super.destroy();
_fileHelper.destroy();
_fileHelper = null;
_binarySwfLoader.destroy();
_binarySwfLoader = null;
_swfProcessor.destroy();
_swfProcessor = null;
_cuke4AS3Server.destroy();
_cuke4AS3Server = null;
if( _mockCucumber != null )
{
if( _mockCucumber.connected )
{
_mockCucumber.close();
}
_mockCucumber = null;
}
}
private function onMatchResponse( event:ProgressEvent, passThroughData:Object ):void
{
var mockCucumber:Socket = ( event.target as Socket );
var jsonString:String = mockCucumber.readUTFBytes( mockCucumber.bytesAvailable );
var dataReceived:Array = JSON.decode( jsonString );
// Ensure that the server said the match was good
assertThat( dataReceived, arrayWithSize( 2 ) );
assertThat( dataReceived, array( equalTo( "success" ), arrayWithSize( 1 ) ) );
var payload:Object = dataReceived[1][0];
assertThat( payload, hasPropertyWithValue( "source", _mockPackageName + "." + _mockClassName ) );
//Only asked it to match one step so id will always be zero
assertThat( payload, hasPropertyWithValue( "id", 0 ) );
assertThat( payload, hasPropertyWithValue( "args", arrayWithSize( 1 ) ) );
var args:Object = payload.args[0];
assertThat( args, allOf( hasPropertyWithValue( "val", _argValue ), hasPropertyWithValue( "pos", 20 ) ) );
assertThat( payload, hasPropertyWithValue( "regexp", "/^" + _stepRegExp + "$/" ) );
}
private function onInvokeResponse( event:ProgressEvent, passThroughData:Object ):void
{
var mockCucumber:Socket = ( event.target as Socket );
var jsonString:String = mockCucumber.readUTFBytes( mockCucumber.bytesAvailable );
var dataReceived:Array = JSON.decode( jsonString );
assertThat( dataReceived, arrayWithSize( 1 ) );
assertThat( dataReceived, array( equalTo( "success" ) ) );
}
}
}