@@ -51,6 +51,7 @@ class MockServerChannel implements ServerCommunicationChannel {
5151 new StreamController <Response >.broadcast ();
5252 StreamController <Notification > notificationController =
5353 new StreamController <Notification >(sync : true );
54+ Completer <Response > errorCompleter;
5455
5556 List <Response > responsesReceived = [];
5657 List <Notification > notificationsReceived = [];
@@ -81,23 +82,34 @@ class MockServerChannel implements ServerCommunicationChannel {
8182 return ;
8283 }
8384 notificationsReceived.add (notification);
85+ if (errorCompleter != null && notification.event == 'server.error' ) {
86+ errorCompleter.completeError (
87+ new ServerError (notification.params['message' ]),
88+ new StackTrace .fromString (notification.params['stackTrace' ]));
89+ }
8490 // Wrap send notification in future to simulate websocket
8591 // TODO(scheglov) ask Dan why and decide what to do
8692// new Future(() => notificationController.add(notification));
8793 notificationController.add (notification);
8894 }
8995
9096 /**
91- * Simulate request/response pair.
97+ * Send the given [request] to the server and return a future that will
98+ * complete when a response associated with the [request] has been received.
99+ * The value of the future will be the received response. If [throwOnError] is
100+ * `true` (the default) then the returned future will throw an exception if a
101+ * server error is reported before the response has been received.
92102 */
93- Future <Response > sendRequest (Request request) {
103+ Future <Response > sendRequest (Request request, {bool throwOnError = true }) {
104+ // TODO(brianwilkerson) Attempt to remove the `throwOnError` parameter and
105+ // have the default behavior be the only behavior.
94106 // No further requests should be sent after the connection is closed.
95107 if (_closed) {
96108 throw new Exception ('sendRequest after connection closed' );
97109 }
98110 // Wrap send request in future to simulate WebSocket.
99111 new Future (() => requestController.add (request));
100- return waitForResponse (request);
112+ return waitForResponse (request, throwOnError : throwOnError );
101113 }
102114
103115 @override
@@ -111,10 +123,28 @@ class MockServerChannel implements ServerCommunicationChannel {
111123 new Future (() => responseController.add (response));
112124 }
113125
114- Future <Response > waitForResponse (Request request) {
126+ /**
127+ * Return a future that will complete when a response associated with the
128+ * given [request] has been received. The value of the future will be the
129+ * received response. If [throwOnError] is `true` (the default) then the
130+ * returned future will throw an exception if a server error is reported
131+ * before the response has been received.
132+ *
133+ * Unlike [sendRequest] , this method assumes that the [request] has already
134+ * been sent to the server.
135+ */
136+ Future <Response > waitForResponse (Request request,
137+ {bool throwOnError = true }) {
138+ // TODO(brianwilkerson) Attempt to remove the `throwOnError` parameter and
139+ // have the default behavior be the only behavior.
115140 String id = request.id;
116- return responseController.stream
117- .firstWhere ((response) => response.id == id);
141+ Future <Response > response =
142+ responseController.stream.firstWhere ((response) => response.id == id);
143+ if (throwOnError) {
144+ errorCompleter ?? = new Completer <Response >();
145+ return Future .any ([response, errorCompleter.future]);
146+ }
147+ return response;
118148 }
119149}
120150
@@ -194,6 +224,16 @@ class MockSource extends StringTypedMock implements Source {
194224 bool exists () => null ;
195225}
196226
227+ class ServerError implements Exception {
228+ final message;
229+
230+ ServerError (this .message);
231+
232+ String toString () {
233+ return "Server Error: $message " ;
234+ }
235+ }
236+
197237class StringTypedMock {
198238 String _toString;
199239
0 commit comments