Fix spawnHybridUri() in the browser (#689)
Closes #688
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 22aa888..a3427cf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.12.24+8
+
+* `spawnHybridUri()` now interprets relative URIs correctly in browser tests.
+
## 0.12.24+7
* Declare support for `async` 2.0.0.
diff --git a/lib/src/frontend/spawn_hybrid.dart b/lib/src/frontend/spawn_hybrid.dart
index 37f9517..2008935 100644
--- a/lib/src/frontend/spawn_hybrid.dart
+++ b/lib/src/frontend/spawn_hybrid.dart
@@ -98,10 +98,17 @@
String absoluteUri;
if (parsedUrl.scheme.isEmpty) {
- var suitePath = Invoker.current.liveTest.suite.path;
- absoluteUri = p.url.join(
- p.url.dirname(p.toUri(p.absolute(suitePath)).toString()),
- parsedUrl.toString());
+ // If we're running in a browser context, the working directory is already
+ // relative to the test file, whereas on the VM the working directory is the
+ // root of the package.
+ if (p.style == p.Style.url) {
+ absoluteUri = p.absolute(parsedUrl.toString());
+ } else {
+ var suitePath = Invoker.current.liveTest.suite.path;
+ absoluteUri = p.url.join(
+ p.url.dirname(p.toUri(p.absolute(suitePath)).toString()),
+ parsedUrl.toString());
+ }
} else {
absoluteUri = uri.toString();
}
diff --git a/pubspec.yaml b/pubspec.yaml
index d60c2d3..86f72f7 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: test
-version: 0.12.24+7
+version: 0.12.24+8
author: Dart Team <misc@dartlang.org>
description: A library for writing dart unit tests.
homepage: https://github.com/dart-lang/test
diff --git a/test/runner/hybrid_test.dart b/test/runner/hybrid_test.dart
index 242b0ca..cec8762 100644
--- a/test/runner/hybrid_test.dart
+++ b/test/runner/hybrid_test.dart
@@ -22,165 +22,13 @@
});
group("spawnHybridUri():", () {
- test("loads a file in a separate isolate connected via StreamChannel",
- () async {
- await d.file("test.dart", """
- import "package:test/test.dart";
-
- void main() {
- test("hybrid emits numbers", () {
- expect(spawnHybridUri("hybrid.dart").stream.toList(),
- completion(equals([1, 2, 3])));
- });
- }
- """).create();
-
- await d.file("hybrid.dart", """
- import "package:stream_channel/stream_channel.dart";
-
- void hybridMain(StreamChannel channel) {
- channel.sink..add(1)..add(2)..add(3)..close();
- }
- """).create();
-
- var test = await runTest(["test.dart"]);
- expect(
- test.stdout,
- containsInOrder(
- ["+0: hybrid emits numbers", "+1: All tests passed!"]));
- await test.shouldExit(0);
+ group("in the VM", () {
+ _spawnHybridUriTests();
});
- test("resolves URIs relative to the test file", () async {
- await d.dir("test/dir/subdir", [
- d.file("test.dart", """
- import "package:test/test.dart";
-
- void main() {
- test("hybrid emits numbers", () {
- expect(spawnHybridUri("hybrid.dart").stream.toList(),
- completion(equals([1, 2, 3])));
- });
- }
- """),
- d.file("hybrid.dart", """
- import "package:stream_channel/stream_channel.dart";
-
- void hybridMain(StreamChannel channel) {
- channel.sink..add(1)..add(2)..add(3)..close();
- }
- """),
- ]).create();
-
- var test = await runTest(["test/dir/subdir/test.dart"]);
- expect(
- test.stdout,
- containsInOrder(
- ["+0: hybrid emits numbers", "+1: All tests passed!"]));
- await test.shouldExit(0);
- });
-
- test("supports absolute file: URIs", () async {
- var url = p.toUri(p.absolute(p.join(d.sandbox, 'hybrid.dart')));
- await d.file("test.dart", """
- import "package:test/test.dart";
-
- void main() {
- test("hybrid emits numbers", () {
- expect(spawnHybridUri("$url").stream.toList(),
- completion(equals([1, 2, 3])));
- });
- }
- """).create();
-
- await d.file("hybrid.dart", """
- import "package:stream_channel/stream_channel.dart";
-
- void hybridMain(StreamChannel channel) {
- channel.sink..add(1)..add(2)..add(3)..close();
- }
- """).create();
-
- var test = await runTest(["test.dart"]);
- expect(
- test.stdout,
- containsInOrder(
- ["+0: hybrid emits numbers", "+1: All tests passed!"]));
- await test.shouldExit(0);
- });
-
- test("supports Uri objects", () async {
- await d.file("test.dart", """
- import "package:test/test.dart";
-
- void main() {
- test("hybrid emits numbers", () {
- expect(spawnHybridUri(Uri.parse("hybrid.dart")).stream.toList(),
- completion(equals([1, 2, 3])));
- });
- }
- """).create();
-
- await d.file("hybrid.dart", """
- import "package:stream_channel/stream_channel.dart";
-
- void hybridMain(StreamChannel channel) {
- channel.sink..add(1)..add(2)..add(3)..close();
- }
- """).create();
-
- var test = await runTest(["test.dart"]);
- expect(
- test.stdout,
- containsInOrder(
- ["+0: hybrid emits numbers", "+1: All tests passed!"]));
- await test.shouldExit(0);
- });
-
- test("rejects non-String, non-Uri objects", () {
- expect(() => spawnHybridUri(123), throwsArgumentError);
- });
-
- test("passes a message to the hybrid isolate", () async {
- await d.file("test.dart", """
- import "package:test/test.dart";
-
- void main() {
- test("hybrid echoes message", () {
- expect(
- spawnHybridUri(Uri.parse("hybrid.dart"), message: 123)
- .stream.first,
- completion(equals(123)));
-
- expect(
- spawnHybridUri(Uri.parse("hybrid.dart"), message: "wow")
- .stream.first,
- completion(equals("wow")));
- });
- }
- """).create();
-
- await d.file("hybrid.dart", """
- import "package:stream_channel/stream_channel.dart";
-
- void hybridMain(StreamChannel channel, Object message) {
- channel.sink..add(message)..close();
- }
- """).create();
-
- var test = await runTest(["test.dart"]);
- expect(
- test.stdout,
- containsInOrder(
- ["+0: hybrid echoes message", "+1: All tests passed!"]));
- await test.shouldExit(0);
- });
-
- test("emits an error from the stream channel if the isolate fails to load",
- () {
- expect(spawnHybridUri("non existent file").stream.first,
- throwsA(new isInstanceOf<IsolateSpawnException>()));
- });
+ group("in the browser", () {
+ _spawnHybridUriTests(["-p", "chrome"]);
+ }, tags: "browser");
});
group("spawnHybridCode()", () {
@@ -544,3 +392,163 @@
});
});
}
+
+/// Defines tests for `spawnHybridUri()`.
+///
+/// If [arguments] is given, it's passed on to the invocation of the test
+/// runner.
+void _spawnHybridUriTests([Iterable<String> arguments]) {
+ arguments ??= [];
+
+ test("loads a file in a separate isolate connected via StreamChannel",
+ () async {
+ await d.file("test.dart", """
+ import "package:test/test.dart";
+
+ void main() {
+ test("hybrid emits numbers", () {
+ expect(spawnHybridUri("hybrid.dart").stream.toList(),
+ completion(equals([1, 2, 3])));
+ });
+ }
+ """).create();
+
+ await d.file("hybrid.dart", """
+ import "package:stream_channel/stream_channel.dart";
+
+ void hybridMain(StreamChannel channel) {
+ channel.sink..add(1)..add(2)..add(3)..close();
+ }
+ """).create();
+
+ var test = await runTest(["test.dart"]..addAll(arguments));
+ expect(test.stdout,
+ containsInOrder(["+0: hybrid emits numbers", "+1: All tests passed!"]));
+ await test.shouldExit(0);
+ });
+
+ test("resolves URIs relative to the test file", () async {
+ await d.dir("test/dir/subdir", [
+ d.file("test.dart", """
+ import "package:test/test.dart";
+
+ void main() {
+ test("hybrid emits numbers", () {
+ expect(spawnHybridUri("hybrid.dart").stream.toList(),
+ completion(equals([1, 2, 3])));
+ });
+ }
+ """),
+ d.file("hybrid.dart", """
+ import "package:stream_channel/stream_channel.dart";
+
+ void hybridMain(StreamChannel channel) {
+ channel.sink..add(1)..add(2)..add(3)..close();
+ }
+ """),
+ ]).create();
+
+ var test = await runTest(["test/dir/subdir/test.dart"]..addAll(arguments));
+ expect(test.stdout,
+ containsInOrder(["+0: hybrid emits numbers", "+1: All tests passed!"]));
+ await test.shouldExit(0);
+ });
+
+ test("supports absolute file: URIs", () async {
+ var url = p.toUri(p.absolute(p.join(d.sandbox, 'hybrid.dart')));
+ await d.file("test.dart", """
+ import "package:test/test.dart";
+
+ void main() {
+ test("hybrid emits numbers", () {
+ expect(spawnHybridUri("$url").stream.toList(),
+ completion(equals([1, 2, 3])));
+ });
+ }
+ """).create();
+
+ await d.file("hybrid.dart", """
+ import "package:stream_channel/stream_channel.dart";
+
+ void hybridMain(StreamChannel channel) {
+ channel.sink..add(1)..add(2)..add(3)..close();
+ }
+ """).create();
+
+ var test = await runTest(["test.dart"]..addAll(arguments));
+ expect(test.stdout,
+ containsInOrder(["+0: hybrid emits numbers", "+1: All tests passed!"]));
+ await test.shouldExit(0);
+ });
+
+ test("supports Uri objects", () async {
+ await d.file("test.dart", """
+ import "package:test/test.dart";
+
+ void main() {
+ test("hybrid emits numbers", () {
+ expect(spawnHybridUri(Uri.parse("hybrid.dart")).stream.toList(),
+ completion(equals([1, 2, 3])));
+ });
+ }
+ """).create();
+
+ await d.file("hybrid.dart", """
+ import "package:stream_channel/stream_channel.dart";
+
+ void hybridMain(StreamChannel channel) {
+ channel.sink..add(1)..add(2)..add(3)..close();
+ }
+ """).create();
+
+ var test = await runTest(["test.dart"]..addAll(arguments));
+ expect(test.stdout,
+ containsInOrder(["+0: hybrid emits numbers", "+1: All tests passed!"]));
+ await test.shouldExit(0);
+ });
+
+ test("rejects non-String, non-Uri objects", () {
+ expect(() => spawnHybridUri(123), throwsArgumentError);
+ });
+
+ test("passes a message to the hybrid isolate", () async {
+ await d.file("test.dart", """
+ import "package:test/test.dart";
+
+ void main() {
+ test("hybrid echoes message", () {
+ expect(
+ spawnHybridUri(Uri.parse("hybrid.dart"), message: 123)
+ .stream.first,
+ completion(equals(123)));
+
+ expect(
+ spawnHybridUri(Uri.parse("hybrid.dart"), message: "wow")
+ .stream.first,
+ completion(equals("wow")));
+ });
+ }
+ """).create();
+
+ await d.file("hybrid.dart", """
+ import "package:stream_channel/stream_channel.dart";
+
+ void hybridMain(StreamChannel channel, Object message) {
+ channel.sink..add(message)..close();
+ }
+ """).create();
+
+ var test = await runTest(["test.dart"]..addAll(arguments));
+ expect(
+ test.stdout,
+ containsInOrder(
+ ["+0: hybrid echoes message", "+1: All tests passed!"]));
+ await test.shouldExit(0);
+ });
+
+ test("emits an error from the stream channel if the isolate fails to load",
+ () {
+ expect(spawnHybridUri("non existent file").stream.first,
+ throwsA(new isInstanceOf<IsolateSpawnException>()));
+ });
+}