2 var url
= require( "url" );
3 var fs
= require( "fs" );
4 var getRawBody
= require( "raw-body" );
8 * Keep in sync with /test/mock.php
11 contentType: function( req
, resp
) {
12 resp
.writeHead( 200, {
13 "content-type": req
.query
.contentType
15 resp
.end( req
.query
.response
);
17 wait: function( req
, resp
) {
18 var wait
= Number( req
.query
.wait
) * 1000;
19 setTimeout( function() {
20 if ( req
.query
.script
) {
21 resp
.writeHead( 200, { "content-type": "text/javascript" } );
23 resp
.writeHead( 200, { "content-type": "text/html" } );
24 resp
.end( "ERROR <script>ok( true, \"mock executed\" );</script>" );
28 name: function( req
, resp
, next
) {
29 resp
.writeHead( 200 );
30 if ( req
.query
.name
=== "foo" ) {
34 getBody( req
).then( function( body
) {
35 if ( body
=== "name=peter" ) {
42 xml: function( req
, resp
, next
) {
43 var content
= "<math><calculation>5-2</calculation><result>3</result></math>";
44 resp
.writeHead( 200, { "content-type": "text/xml" } );
46 if ( req
.query
.cal
=== "5-2" ) {
50 getBody( req
).then( function( body
) {
51 if ( body
=== "cal=5-2" ) {
54 resp
.end( "<error>ERROR</error>" );
58 atom: function( req
, resp
, next
) {
59 resp
.writeHead( 200, { "content-type": "atom+xml" } );
60 resp
.end( "<root><element /></root>" );
62 script: function( req
, resp
) {
63 if ( req
.query
.header
=== "ecma" ) {
64 resp
.writeHead( 200, { "content-type": "application/ecmascript" } );
65 } else if ( req
.query
.header
) {
66 resp
.writeHead( 200, { "content-type": "text/javascript" } );
68 resp
.writeHead( 200, { "content-type": "text/html" } );
70 resp
.end( "ok( true, \"mock executed\" );" );
72 testbar: function( req
, resp
) {
73 resp
.writeHead( 200 );
75 "this.testBar = 'bar'; " +
76 "jQuery('#ap').html('bar'); " +
77 "ok( true, 'mock executed');"
80 json: function( req
, resp
) {
81 if ( req
.query
.header
) {
82 resp
.writeHead( 200, { "content-type": "application/json" } );
84 if ( req
.query
.array
) {
85 resp
.end( JSON
.stringify(
86 [ { name
: "John", age
: 21 }, { name
: "Peter", age
: 25 } ]
89 resp
.end( JSON
.stringify(
90 { data
: { lang
: "en", length
: 25 } }
94 jsonp: function( req
, resp
, next
) {
96 if ( req
.query
.callback
) {
97 callback
= Promise
.resolve( req
.query
.callback
);
98 } else if ( req
.method
=== "GET" ) {
99 callback
= Promise
.resolve( req
.url
.match( /^.+\/([^\/?.]+)\?.+$/ )[ 1 ] );
101 callback
= getBody( req
).then( function( body
) {
102 return body
.trim().replace( "callback=", "" );
105 var json
= req
.query
.array
?
107 [ { name
: "John", age
: 21 }, { name
: "Peter", age
: 25 } ]
110 { data
: { lang
: "en", length
: 25 } }
112 callback
.then( function( cb
) {
113 resp
.end( cb
+ "(" + json
+ ")" );
116 xmlOverJsonp: function( req
, resp
) {
117 var callback
= req
.query
.callback
;
118 var body
= fs
.readFileSync( __dirname
+ "/data/with_fries.xml" ).toString();
119 resp
.writeHead( 200 );
120 resp
.end( callback
+ "(" + JSON
.stringify( body
) + ")\n" );
122 error: function( req
, resp
) {
123 if ( req
.query
.json
) {
124 resp
.writeHead( 400, { "content-type": "application/json" } );
125 resp
.end( "{ \"code\": 40, \"message\": \"Bad Request\" }" );
127 resp
.writeHead( 400 );
128 resp
.end( "plain text message" );
131 headers: function( req
, resp
) {
132 resp
.writeHead( 200, {
133 "Sample-Header": "Hello World",
135 "Sample-Header2": "Hello World 2"
137 req
.query
.keys
.split( "|" ).forEach( function( key
) {
138 if ( req
.headers
[ key
.toLowerCase() ] ) {
139 resp
.write( key
+ ": " + req
.headers
[ key
.toLowerCase() ] + "\n" );
144 echoData: function( req
, resp
, next
) {
145 getBody( req
).then( function( body
) {
149 echoQuery: function( req
, resp
) {
150 resp
.end( req
.parsed
.search
.slice( 1 ) );
152 echoMethod: function( req
, resp
) {
153 resp
.end( req
.method
);
155 echoHtml: function( req
, resp
, next
) {
156 resp
.writeHead( 200, { "Content-Type": "text/html" } );
157 resp
.write( "<div id='method'>" + req
.method
+ "</div>" );
158 resp
.write( "<div id='query'>" + req
.parsed
.search
.slice( 1 ) + "</div>" );
159 getBody( req
).then( function( body
) {
160 resp
.write( "<div id='data'>" + body
+ "</div>" );
164 etag: function( req
, resp
) {
165 var hash
= Number( req
.query
.ts
).toString( 36 );
166 var etag
= "W/\"" + hash
+ "\"";
167 if ( req
.headers
[ "if-none-match" ] === etag
) {
168 resp
.writeHead( 304 );
172 resp
.writeHead( 200, {
177 ims: function( req
, resp
, next
) {
178 var ts
= req
.query
.ts
;
179 if ( req
.headers
[ "if-modified-since" ] === ts
) {
180 resp
.writeHead( 304 );
184 resp
.writeHead( 200, {
189 status: function( req
, resp
, next
) {
190 resp
.writeHead( Number( req
.query
.code
) );
193 testHTML: function( req
, resp
) {
194 resp
.writeHead( 200, { "Content-Type": "text/html" } );
195 var body
= fs
.readFileSync( __dirname
+ "/data/test.include.html" ).toString();
196 body
= body
.replace( /{{baseURL}}/g, req
.query
.baseURL
);
199 cspFrame: function( req
, resp
) {
200 resp
.writeHead( 200, {
201 "Content-Type": "text/html",
202 "Content-Security-Policy": "default-src 'self'; report-uri /base/test/data/mock.php?action=cspLog"
204 var body
= fs
.readFileSync( __dirname
+ "/data/csp.include.html" ).toString();
207 cspLog: function( req
, resp
) {
209 resp
.writeHead( 200 );
212 cspClean: function( req
, resp
) {
214 resp
.writeHead( 200 );
219 "test/data/mock.php": function( req
, resp
, next
) {
220 if ( !mocks
[ req
.query
.action
] ) {
221 resp
.writeHead( 400 );
222 resp
.end( "Invalid action query.\n" );
223 console
.log( "Invalid action query:", req
.method
, req
.url
);
226 mocks
[ req
.query
.action
]( req
, resp
, next
);
228 "test/data/support/csp.log": function( req
, resp
) {
229 resp
.writeHead( 200 );
232 "test/data/404.txt": function( req
, resp
) {
233 resp
.writeHead( 404 );
239 * Connect-compatible middleware factory for mocking server responses.
240 * Used by Ajax unit tests when run via Karma.
242 * Despite Karma using Express, it uses Connect to deal with custom middleware,
243 * which passes the raw Node Request and Response objects instead of the
244 * Express versions of these (e.g. no req.path, req.query, resp.set).
246 function MockserverMiddlewareFactory() {
248 * @param {http.IncomingMessage} req
249 * @param {http.ServerResponse} resp
250 * @param {Function} next Continue request handling
252 return function( req
, resp
, next
) {
253 var method
= req
.method
,
254 parsed
= url
.parse( req
.url
, /* parseQuery */ true ),
255 path
= parsed
.pathname
.replace( /^\/base\//, "" ),
256 query
= parsed
.query
,
257 subReq
= Object
.assign( Object
.create( req
), {
262 if ( /^test\/data\/mock.php\//.test( path
) ) {
263 // Support REST-like Apache PathInfo
264 path
= "test\/data\/mock.php";
267 if ( !handlers
[ path
] ) {
272 handlers
[ path
]( subReq
, resp
, next
);
276 function getBody( req
) {
277 return req
.method
!== "POST" ?
278 Promise
.resolve( "" ) :
284 module
.exports
= MockserverMiddlewareFactory
;