Index: lib/src/runner/browser/browser_manager.dart |
diff --git a/lib/src/runner/browser/browser_manager.dart b/lib/src/runner/browser/browser_manager.dart |
index d03bd66ef3d0623cdb94ed590340e6ea306922ec..55187482379426559dde99bec11c81ee211d2b00 100644 |
--- a/lib/src/runner/browser/browser_manager.dart |
+++ b/lib/src/runner/browser/browser_manager.dart |
@@ -42,6 +42,12 @@ class BrowserManager { |
/// at once. |
final _pool = new Pool(8); |
+ /// The ID of the next suite to be loaded. |
+ /// |
+ /// This is used to ensure that the suites can be referred to consistently |
+ /// across the client and server. |
+ int _suiteId = 0; |
+ |
/// Creates a new BrowserManager that communicates with [browser] over |
/// [webSocket]. |
BrowserManager(this.browser, CompatibleWebSocket webSocket) |
@@ -66,17 +72,30 @@ class BrowserManager { |
// The stream may close before emitting a value if the browser is killed |
// prematurely (e.g. via Control-C). |
- var suiteChannel = _channel.virtualChannel(); |
+ var suiteVirtualChannel = _channel.virtualChannel(); |
+ var suiteId = _suiteId++; |
+ var suiteChannel; |
+ |
+ closeIframe() { |
+ suiteChannel.sink.close(); |
+ _channel.sink.add({ |
+ "command": "closeSuite", |
+ "id": suiteId |
+ }); |
+ } |
+ |
var response = await _pool.withResource(() { |
_channel.sink.add({ |
"command": "loadSuite", |
"url": url.toString(), |
- "channel": suiteChannel.id |
+ "id": _suiteId++, |
+ "channel": suiteVirtualChannel.id |
}); |
// Create a nested MultiChannel because the iframe will be using a channel |
// wrapped within the host's channel. |
- suiteChannel = new MultiChannel(suiteChannel.stream, suiteChannel.sink); |
+ suiteChannel = new MultiChannel( |
+ suiteVirtualChannel.stream, suiteVirtualChannel.sink); |
var completer = new Completer(); |
suiteChannel.stream.listen((response) { |
@@ -97,13 +116,18 @@ class BrowserManager { |
}); |
}); |
- if (response == null) return null; |
+ if (response == null) { |
+ closeIframe(); |
+ return null; |
+ } |
if (response["type"] == "loadException") { |
+ closeIframe(); |
throw new LoadException(path, response["message"]); |
} |
if (response["type"] == "error") { |
+ closeIframe(); |
var asyncError = RemoteException.deserialize(response["error"]); |
await new Future.error( |
new LoadException(path, asyncError.error), |
@@ -115,6 +139,6 @@ class BrowserManager { |
var testChannel = suiteChannel.virtualChannel(test['channel']); |
return new IframeTest(test['name'], testMetadata, testChannel, |
mapper: mapper); |
- }), metadata: metadata, path: path); |
+ }), metadata: metadata, path: path, onClose: () => closeIframe()); |
} |
} |