OLD | NEW |
(Empty) | |
| 1 library pub_tests; |
| 2 import 'dart:async'; |
| 3 import 'dart:convert'; |
| 4 import 'dart:io'; |
| 5 import 'package:http/http.dart' as http; |
| 6 import 'package:scheduled_test/scheduled_process.dart'; |
| 7 import 'package:scheduled_test/scheduled_stream.dart'; |
| 8 import 'package:scheduled_test/scheduled_test.dart'; |
| 9 import 'package:stack_trace/stack_trace.dart'; |
| 10 import '../../lib/src/utils.dart'; |
| 11 import '../descriptor.dart' as d; |
| 12 import '../test_pub.dart'; |
| 13 ScheduledProcess _pubServer; |
| 14 int _adminPort; |
| 15 final _ports = new Map<String, int>(); |
| 16 Completer _portsCompleter; |
| 17 WebSocket _webSocket; |
| 18 Stream _webSocketBroadcastStream; |
| 19 const REWRITE_TRANSFORMER = """ |
| 20 import 'dart:async'; |
| 21 |
| 22 import 'package:barback/barback.dart'; |
| 23 |
| 24 class RewriteTransformer extends Transformer { |
| 25 RewriteTransformer.asPlugin(); |
| 26 |
| 27 String get allowedExtensions => '.txt'; |
| 28 |
| 29 Future apply(Transform transform) { |
| 30 return transform.primaryInput.readAsString().then((contents) { |
| 31 var id = transform.primaryInput.id.changeExtension(".out"); |
| 32 transform.addOutput(new Asset.fromString(id, "\$contents.out")); |
| 33 }); |
| 34 } |
| 35 } |
| 36 """; |
| 37 const LAZY_TRANSFORMER = """ |
| 38 import 'dart:async'; |
| 39 |
| 40 import 'package:barback/barback.dart'; |
| 41 |
| 42 class LazyRewriteTransformer extends Transformer implements LazyTransformer { |
| 43 LazyRewriteTransformer.asPlugin(); |
| 44 |
| 45 String get allowedExtensions => '.txt'; |
| 46 |
| 47 Future apply(Transform transform) { |
| 48 transform.logger.info('Rewriting \${transform.primaryInput.id}.'); |
| 49 return transform.primaryInput.readAsString().then((contents) { |
| 50 var id = transform.primaryInput.id.changeExtension(".out"); |
| 51 transform.addOutput(new Asset.fromString(id, "\$contents.out")); |
| 52 }); |
| 53 } |
| 54 |
| 55 Future declareOutputs(DeclaringTransform transform) { |
| 56 transform.declareOutput(transform.primaryId.changeExtension(".out")); |
| 57 return new Future.value(); |
| 58 } |
| 59 } |
| 60 """; |
| 61 const NOT_SERVED = 1; |
| 62 String dartTransformer(String id, {String import}) { |
| 63 if (import != null) { |
| 64 id = '$id imports \${$import.TOKEN}'; |
| 65 import = 'import "package:$import/$import.dart" as $import;'; |
| 66 } else { |
| 67 import = ''; |
| 68 } |
| 69 return """ |
| 70 import 'dart:async'; |
| 71 |
| 72 import 'package:barback/barback.dart'; |
| 73 $import |
| 74 |
| 75 import 'dart:io'; |
| 76 |
| 77 const TOKEN = "$id"; |
| 78 |
| 79 final _tokenRegExp = new RegExp(r'^const TOKEN = "(.*?)";\$', multiLine: true); |
| 80 |
| 81 class DartTransformer extends Transformer { |
| 82 final BarbackSettings _settings; |
| 83 |
| 84 DartTransformer.asPlugin(this._settings); |
| 85 |
| 86 String get allowedExtensions => '.dart'; |
| 87 |
| 88 Future apply(Transform transform) { |
| 89 return transform.primaryInput.readAsString().then((contents) { |
| 90 transform.addOutput(new Asset.fromString(transform.primaryInput.id, |
| 91 contents.replaceAllMapped(_tokenRegExp, (match) { |
| 92 var token = TOKEN; |
| 93 var addition = _settings.configuration["addition"]; |
| 94 if (addition != null) token += addition; |
| 95 return 'const TOKEN = "(\${match[1]}, \$token)";'; |
| 96 }))); |
| 97 }); |
| 98 } |
| 99 } |
| 100 """; |
| 101 } |
| 102 ScheduledProcess startPubServe({Iterable<String> args, bool createWebDir: true}) |
| 103 { |
| 104 var pubArgs = ["serve", "--port=0", "--force-poll", "--log-admin-url"]; |
| 105 if (args != null) pubArgs.addAll(args); |
| 106 currentSchedule.timeout *= 1.5; |
| 107 if (createWebDir) d.dir(appPath, [d.dir("web")]).create(); |
| 108 return startPub(args: pubArgs); |
| 109 } |
| 110 ScheduledProcess pubServe({bool shouldGetFirst: false, bool createWebDir: true, |
| 111 Iterable<String> args}) { |
| 112 _pubServer = startPubServe(args: args, createWebDir: createWebDir); |
| 113 _portsCompleter = new Completer(); |
| 114 currentSchedule.onComplete.schedule(() { |
| 115 _portsCompleter = null; |
| 116 _ports.clear(); |
| 117 if (_webSocket != null) { |
| 118 _webSocket.close(); |
| 119 _webSocket = null; |
| 120 _webSocketBroadcastStream = null; |
| 121 } |
| 122 }); |
| 123 if (shouldGetFirst) { |
| 124 _pubServer.stdout.expect( |
| 125 consumeThrough( |
| 126 anyOf(["Got dependencies!", matches(new RegExp(r"^Changed \d+ depend
enc"))]))); |
| 127 } |
| 128 _pubServer.stdout.expect(startsWith("Loading source assets...")); |
| 129 _pubServer.stdout.expect(consumeWhile(matches("Loading .* transformers..."))); |
| 130 _pubServer.stdout.expect(predicate(_parseAdminPort)); |
| 131 _pubServer.stdout.expect( |
| 132 consumeWhile(predicate(_parsePort, 'emits server url'))); |
| 133 schedule(() { |
| 134 expect(_ports, isNot(isEmpty)); |
| 135 _portsCompleter.complete(); |
| 136 }); |
| 137 return _pubServer; |
| 138 } |
| 139 final _parsePortRegExp = new RegExp(r"([^ ]+) +on http://localhost:(\d+)"); |
| 140 bool _parseAdminPort(String line) { |
| 141 var match = _parsePortRegExp.firstMatch(line); |
| 142 if (match == null) return false; |
| 143 _adminPort = int.parse(match[2]); |
| 144 return true; |
| 145 } |
| 146 bool _parsePort(String line) { |
| 147 var match = _parsePortRegExp.firstMatch(line); |
| 148 if (match == null) return false; |
| 149 _ports[match[1]] = int.parse(match[2]); |
| 150 return true; |
| 151 } |
| 152 void endPubServe() { |
| 153 _pubServer.kill(); |
| 154 } |
| 155 Future<http.Response> scheduleRequest(String urlPath, {String root}) { |
| 156 return schedule(() { |
| 157 return http.get(_getServerUrlSync(root, urlPath)); |
| 158 }, "request $urlPath"); |
| 159 } |
| 160 void requestShouldSucceed(String urlPath, expectation, {String root, headers}) { |
| 161 scheduleRequest(urlPath, root: root).then((response) { |
| 162 if (expectation != null) expect(response.body, expectation); |
| 163 if (headers != null) expect(response.headers, headers); |
| 164 }); |
| 165 } |
| 166 void requestShould404(String urlPath, {String root}) { |
| 167 scheduleRequest(urlPath, root: root).then((response) { |
| 168 expect(response.statusCode, equals(404)); |
| 169 }); |
| 170 } |
| 171 void requestShouldRedirect(String urlPath, redirectTarget, {String root}) { |
| 172 schedule(() { |
| 173 var request = |
| 174 new http.Request("GET", Uri.parse(_getServerUrlSync(root, urlPath))); |
| 175 request.followRedirects = false; |
| 176 return request.send().then((response) { |
| 177 expect(response.statusCode ~/ 100, equals(3)); |
| 178 expect(response.headers, containsPair('location', redirectTarget)); |
| 179 }); |
| 180 }, "request $urlPath"); |
| 181 } |
| 182 void postShould405(String urlPath, {String root}) { |
| 183 schedule(() { |
| 184 return http.post(_getServerUrlSync(root, urlPath)).then((response) { |
| 185 expect(response.statusCode, equals(405)); |
| 186 }); |
| 187 }, "request $urlPath"); |
| 188 } |
| 189 void requestShouldNotConnect(String urlPath, {String root}) { |
| 190 schedule(() { |
| 191 return expect( |
| 192 http.get(_getServerUrlSync(root, urlPath)), |
| 193 throwsA(new isInstanceOf<SocketException>())); |
| 194 }, "request $urlPath"); |
| 195 } |
| 196 void waitForBuildSuccess() => |
| 197 _pubServer.stdout.expect(consumeThrough(contains("successfully"))); |
| 198 Future _ensureWebSocket() { |
| 199 if (_webSocket != null) return new Future.value(); |
| 200 expect(_pubServer, isNotNull); |
| 201 expect(_adminPort, isNotNull); |
| 202 return WebSocket.connect("ws://localhost:$_adminPort").then((socket) { |
| 203 _webSocket = socket; |
| 204 _webSocketBroadcastStream = _webSocket.map(JSON.decode).asBroadcastStream(); |
| 205 }); |
| 206 } |
| 207 void closeWebSocket() { |
| 208 schedule(() { |
| 209 return _ensureWebSocket().then((_) => _webSocket.close()).then((_) => _webSo
cket = |
| 210 null); |
| 211 }, "closing web socket"); |
| 212 } |
| 213 Future<Map> webSocketRequest(String method, [Map params]) { |
| 214 var completer = new Completer(); |
| 215 schedule(() { |
| 216 return Future.wait( |
| 217 [_ensureWebSocket(), awaitObject(params)]).then((results) { |
| 218 var resolvedParams = results[1]; |
| 219 chainToCompleter( |
| 220 currentSchedule.wrapFuture(_jsonRpcRequest(method, resolvedParams)), |
| 221 completer); |
| 222 }); |
| 223 }, "send $method with $params to web socket"); |
| 224 return completer.future; |
| 225 } |
| 226 Future<Map> expectWebSocketResult(String method, Map params, result) { |
| 227 return schedule(() { |
| 228 return Future.wait( |
| 229 [webSocketRequest(method, params), awaitObject(result)]).then((results)
{ |
| 230 var response = results[0]; |
| 231 var resolvedResult = results[1]; |
| 232 expect(response["result"], resolvedResult); |
| 233 return response["result"]; |
| 234 }); |
| 235 }, "send $method with $params to web socket and expect $result"); |
| 236 } |
| 237 Future expectWebSocketError(String method, Map params, errorCode, errorMessage, |
| 238 {data}) { |
| 239 return schedule(() { |
| 240 return webSocketRequest(method, params).then((response) { |
| 241 expect(response["error"]["code"], errorCode); |
| 242 expect(response["error"]["message"], errorMessage); |
| 243 if (data != null) { |
| 244 expect(response["error"]["data"], data); |
| 245 } |
| 246 return response["error"]["data"]; |
| 247 }); |
| 248 }, "send $method with $params to web socket and expect error $errorCode"); |
| 249 } |
| 250 Future expectNotServed(String root) { |
| 251 return schedule(() { |
| 252 expect(_ports.containsKey(root), isFalse); |
| 253 }); |
| 254 } |
| 255 var _rpcId = 0; |
| 256 Future<Map> _jsonRpcRequest(String method, [Map params]) { |
| 257 var id = _rpcId++; |
| 258 var message = { |
| 259 "jsonrpc": "2.0", |
| 260 "method": method, |
| 261 "id": id |
| 262 }; |
| 263 if (params != null) message["params"] = params; |
| 264 _webSocket.add(JSON.encode(message)); |
| 265 return Chain.track( |
| 266 _webSocketBroadcastStream.firstWhere( |
| 267 (response) => response["id"] == id)).then((value) { |
| 268 currentSchedule.addDebugInfo( |
| 269 "Web Socket request $method with params $params\n" "Result: $value"); |
| 270 expect(value["id"], equals(id)); |
| 271 return value; |
| 272 }); |
| 273 } |
| 274 Future<String> getServerUrl([String root, String path]) => |
| 275 _portsCompleter.future.then((_) => _getServerUrlSync(root, path)); |
| 276 registerServerPort(String root, int port) { |
| 277 _ports[root] = port; |
| 278 } |
| 279 String _getServerUrlSync([String root, String path]) { |
| 280 if (root == null) root = 'web'; |
| 281 expect(_ports, contains(root)); |
| 282 var url = "http://localhost:${_ports[root]}"; |
| 283 if (path != null) url = "$url/$path"; |
| 284 return url; |
| 285 } |
OLD | NEW |