Switch from IOSink to StringSink (#1105)
Towards #1100
The ExpandedReporter needs to work on the web platform. It worked before
because it only used `print` which works everywhere.
- Change the argument to `StringSink` which can be supported on every
platform.
- Remove the `dart:io` import from the expanded reporter.
- Make the `sink` argument non-optional for the expanded reporter.
- Add a `PrintSink` implementation that buffers writes until the content
ends with a newline and then calls `print`.
diff --git a/pkgs/test_core/CHANGELOG.md b/pkgs/test_core/CHANGELOG.md
index 93ea471..01601e2 100644
--- a/pkgs/test_core/CHANGELOG.md
+++ b/pkgs/test_core/CHANGELOG.md
@@ -1,6 +1,6 @@
## 0.2.15-dev
-* Add an `IOSink` argument to reporters to prepare for reporting to a file.
+* Add a `StringSink` argument to reporters to prepare for reporting to a file.
## 0.2.14
diff --git a/pkgs/test_core/lib/src/runner/configuration/reporters.dart b/pkgs/test_core/lib/src/runner/configuration/reporters.dart
index d9ff380..7fe1656 100644
--- a/pkgs/test_core/lib/src/runner/configuration/reporters.dart
+++ b/pkgs/test_core/lib/src/runner/configuration/reporters.dart
@@ -15,7 +15,7 @@
/// Constructs a reporter for the provided engine with the provided
/// configuration.
-typedef ReporterFactory = Reporter Function(Configuration, Engine, IOSink);
+typedef ReporterFactory = Reporter Function(Configuration, Engine, StringSink);
/// Container for a reporter description and corresponding factory.
class ReporterDetails {
@@ -31,12 +31,11 @@
final _allReporters = <String, ReporterDetails>{
"expanded": ReporterDetails(
"A separate line for each update.",
- (config, engine, sink) => ExpandedReporter.watch(engine,
+ (config, engine, sink) => ExpandedReporter.watch(engine, sink,
color: config.color,
printPath: config.paths.length > 1 ||
Directory(config.paths.single).existsSync(),
- printPlatform: config.suiteDefaults.runtimes.length > 1,
- sink: sink)),
+ printPlatform: config.suiteDefaults.runtimes.length > 1)),
"compact": ReporterDetails("A single line, updated continuously.",
(_, engine, sink) => CompactReporter.watch(engine, sink)),
"json": ReporterDetails(
diff --git a/pkgs/test_core/lib/src/runner/reporter/compact.dart b/pkgs/test_core/lib/src/runner/reporter/compact.dart
index d8166ae..7827811 100644
--- a/pkgs/test_core/lib/src/runner/reporter/compact.dart
+++ b/pkgs/test_core/lib/src/runner/reporter/compact.dart
@@ -56,7 +56,7 @@
/// The engine used to run the tests.
final Engine _engine;
- final IOSink _sink;
+ final StringSink _sink;
/// A stopwatch that tracks the duration of the full run.
final _stopwatch = Stopwatch();
@@ -103,7 +103,7 @@
/// Watches the tests run by [engine] and prints their results to the
/// terminal.
- static CompactReporter watch(Engine engine, IOSink sink) =>
+ static CompactReporter watch(Engine engine, StringSink sink) =>
CompactReporter._(engine, sink);
CompactReporter._(this._engine, this._sink) {
diff --git a/pkgs/test_core/lib/src/runner/reporter/expanded.dart b/pkgs/test_core/lib/src/runner/reporter/expanded.dart
index 9e87345..87588d0 100644
--- a/pkgs/test_core/lib/src/runner/reporter/expanded.dart
+++ b/pkgs/test_core/lib/src/runner/reporter/expanded.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
-import 'dart:io';
import 'package:test_api/src/backend/live_test.dart'; // ignore: implementation_imports
import 'package:test_api/src/backend/message.dart'; // ignore: implementation_imports
@@ -85,7 +84,7 @@
/// The set of all subscriptions to various streams.
final _subscriptions = Set<StreamSubscription>();
- final IOSink _sink;
+ final StringSink _sink;
// TODO(nweiz): Get configuration from [Configuration.current] once we have
// cross-platform imports.
@@ -96,26 +95,16 @@
/// won't. If [printPath] is `true`, this will print the path name as part of
/// the test description. Likewise, if [printPlatform] is `true`, this will
/// print the platform as part of the test description.
- static ExpandedReporter watch(Engine engine,
- {bool color = true,
- bool printPath = true,
- bool printPlatform = true,
- IOSink sink}) {
- return ExpandedReporter._(engine,
- color: color,
- printPath: printPath,
- printPlatform: printPlatform,
- sink: sink ?? stdout);
+ static ExpandedReporter watch(Engine engine, StringSink sink,
+ {bool color = true, bool printPath = true, bool printPlatform = true}) {
+ return ExpandedReporter._(engine, sink,
+ color: color, printPath: printPath, printPlatform: printPlatform);
}
- ExpandedReporter._(this._engine,
- {bool color = true,
- bool printPath = true,
- bool printPlatform = true,
- IOSink sink})
+ ExpandedReporter._(this._engine, this._sink,
+ {bool color = true, bool printPath = true, bool printPlatform = true})
: _printPath = printPath,
_printPlatform = printPlatform,
- _sink = sink,
_color = color,
_green = color ? '\u001b[32m' : '',
_red = color ? '\u001b[31m' : '',
diff --git a/pkgs/test_core/lib/src/runner/reporter/json.dart b/pkgs/test_core/lib/src/runner/reporter/json.dart
index 2a2bd12..eb3c9fb 100644
--- a/pkgs/test_core/lib/src/runner/reporter/json.dart
+++ b/pkgs/test_core/lib/src/runner/reporter/json.dart
@@ -4,7 +4,7 @@
import 'dart:async';
import 'dart:convert';
-import 'dart:io' show IOSink, pid;
+import 'dart:io' show pid;
import 'package:path/path.dart' as p;
@@ -33,7 +33,7 @@
/// The engine used to run the tests.
final Engine _engine;
- final IOSink _sink;
+ final StringSink _sink;
/// A stopwatch that tracks the duration of the full run.
final _stopwatch = Stopwatch();
@@ -63,7 +63,7 @@
var _nextID = 0;
/// Watches the tests run by [engine] and prints their results as JSON.
- static JsonReporter watch(Engine engine, IOSink sink) =>
+ static JsonReporter watch(Engine engine, StringSink sink) =>
JsonReporter._(engine, sink);
JsonReporter._(this._engine, this._sink) : _config = Configuration.current {
diff --git a/pkgs/test_core/lib/src/util/print_sink.dart b/pkgs/test_core/lib/src/util/print_sink.dart
new file mode 100644
index 0000000..3409770
--- /dev/null
+++ b/pkgs/test_core/lib/src/util/print_sink.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class PrintSink implements StringSink {
+ final _buffer = StringBuffer();
+
+ @override
+ void write(Object obj) {
+ _buffer.write(obj);
+ _flush();
+ }
+
+ @override
+ void writeAll(Iterable objects, [String separator = '']) {
+ _buffer.writeAll(objects, separator ?? '');
+ _flush();
+ }
+
+ @override
+ void writeCharCode(int charCode) {
+ _buffer.writeCharCode(charCode);
+ _flush();
+ }
+
+ @override
+ void writeln([Object obj = '']) {
+ _buffer.writeln(obj ?? '');
+ _flush();
+ }
+
+ /// [print] if the content available ends with a newline.
+ void _flush() {
+ if ('$_buffer'.endsWith('\n')) {
+ print(_buffer);
+ _buffer.clear();
+ }
+ }
+}
diff --git a/pkgs/test_core/lib/test_core.dart b/pkgs/test_core/lib/test_core.dart
index bcf3145..3e937c0 100644
--- a/pkgs/test_core/lib/test_core.dart
+++ b/pkgs/test_core/lib/test_core.dart
@@ -22,6 +22,7 @@
import 'src/runner/reporter/expanded.dart';
import 'src/runner/runner_suite.dart';
import 'src/runner/suite.dart';
+import 'src/util/print_sink.dart';
export 'package:matcher/matcher.dart';
// Hide implementations which don't support being run directly.
@@ -59,7 +60,7 @@
var engine = Engine();
engine.suiteSink.add(suite);
engine.suiteSink.close();
- ExpandedReporter.watch(engine,
+ ExpandedReporter.watch(engine, PrintSink(),
color: true, printPath: false, printPlatform: false);
var success = await runZoned(() => Invoker.guard(engine.run),