Index: test/codegen/unittest.dart |
diff --git a/test/codegen/unittest.dart b/test/codegen/unittest.dart |
index 2b973607985763976351df3eff67703ac58613da..30b4c495d2b1e3dcbd01ec502c36779b38c411c1 100644 |
--- a/test/codegen/unittest.dart |
+++ b/test/codegen/unittest.dart |
@@ -11,6 +11,113 @@ import 'dart:js'; |
import 'package:matcher/matcher.dart'; |
export 'package:matcher/matcher.dart'; |
+// from matcher/throws_matcher.dart |
+ |
+Function _wrapAsync = (Function f, [id]) => f; |
+ |
+/// This can be used to match two kinds of objects: |
+/// |
+/// * A [Function] that throws an exception when called. The function cannot |
+/// take any arguments. If you want to test that a function expecting |
+/// arguments throws, wrap it in another zero-argument function that calls |
+/// the one you want to test. |
+/// |
+/// * A [Future] that completes with an exception. Note that this creates an |
+/// asynchronous expectation. The call to `expect()` that includes this will |
+/// return immediately and execution will continue. Later, when the future |
+/// completes, the actual expectation will run. |
+const Matcher throws = const Throws(); |
+ |
+/// This can be used to match two kinds of objects: |
+/// |
+/// * A [Function] that throws an exception when called. The function cannot |
+/// take any arguments. If you want to test that a function expecting |
+/// arguments throws, wrap it in another zero-argument function that calls |
+/// the one you want to test. |
+/// |
+/// * A [Future] that completes with an exception. Note that this creates an |
+/// asynchronous expectation. The call to `expect()` that includes this will |
+/// return immediately and execution will continue. Later, when the future |
+/// completes, the actual expectation will run. |
+/// |
+/// In both cases, when an exception is thrown, this will test that the exception |
+/// object matches [matcher]. If [matcher] is not an instance of [Matcher], it |
+/// will implicitly be treated as `equals(matcher)`. |
+Matcher throwsA(matcher) => new Throws(wrapMatcher(matcher)); |
+ |
+class Throws extends Matcher { |
+ final Matcher _matcher; |
+ |
+ const Throws([Matcher matcher]) : this._matcher = matcher; |
+ |
+ bool matches(item, Map matchState) { |
+ if (item is! Function && item is! Future) return false; |
+ if (item is Future) { |
+ var done = _wrapAsync((fn) => fn()); |
+ |
+ // Queue up an asynchronous expectation that validates when the future |
+ // completes. |
+ item.then((value) { |
+ done(() { |
+ fail("Expected future to fail, but succeeded with '$value'."); |
+ }); |
+ }, onError: (error, trace) { |
+ done(() { |
+ if (_matcher == null) return; |
+ var reason; |
+ if (trace != null) { |
+ var stackTrace = trace.toString(); |
+ stackTrace = " ${stackTrace.replaceAll("\n", "\n ")}"; |
+ reason = "Actual exception trace:\n$stackTrace"; |
+ } |
+ expect(error, _matcher, reason: reason); |
+ }); |
+ }); |
+ // It hasn't failed yet. |
+ return true; |
+ } |
+ |
+ try { |
+ item(); |
+ return false; |
+ } catch (e, s) { |
+ if (_matcher == null || _matcher.matches(e, matchState)) { |
+ return true; |
+ } else { |
+ addStateInfo(matchState, {'exception': e, 'stack': s}); |
+ return false; |
+ } |
+ } |
+ } |
+ |
+ Description describe(Description description) { |
+ if (_matcher == null) { |
+ return description.add("throws"); |
+ } else { |
+ return description.add('throws ').addDescriptionOf(_matcher); |
+ } |
+ } |
+ |
+ Description describeMismatch( |
+ item, Description mismatchDescription, Map matchState, bool verbose) { |
+ if (item is! Function && item is! Future) { |
+ return mismatchDescription.add('is not a Function or Future'); |
+ } else if (_matcher == null || matchState['exception'] == null) { |
+ return mismatchDescription.add('did not throw'); |
+ } else { |
+ mismatchDescription |
+ .add('threw ') |
+ .addDescriptionOf(matchState['exception']); |
+ if (verbose) { |
+ mismatchDescription.add(' at ').add(matchState['stack'].toString()); |
+ } |
+ return mismatchDescription; |
+ } |
+ } |
+} |
+ |
+// End of matcher/throws_matcher.dart |
+ |
void group(String name, void body()) => context.callMethod('suite', [name, body]); |
void test(String name, body(), {String skip}) { |
@@ -31,7 +138,6 @@ void test(String name, body(), {String skip}) { |
result['async'] = 1; |
} |
- |
// TODO(jmesserly): everything below this was stolen from |
// package:test/src/frontend/expect.dart |
@@ -44,6 +150,54 @@ class TestFailure { |
String toString() => message; |
} |
+/// An individual unit test. |
+abstract class TestCase { |
+ /// A unique numeric identifier for this test case. |
+ int get id; |
+ |
+ /// A description of what the test is specifying. |
+ String get description; |
+ |
+ /// The error or failure message for the tests. |
+ /// |
+ /// Initially an empty string. |
+ String get message; |
+ |
+ /// The result of the test case. |
+ /// |
+ /// If the test case has is completed, this will be one of [PASS], [FAIL], or |
+ /// [ERROR]. Otherwise, it will be `null`. |
+ String get result; |
+ |
+ /// Returns whether this test case passed. |
+ bool get passed; |
+ |
+ /// The stack trace for the error that caused this test case to fail, or |
+ /// `null` if it succeeded. |
+ StackTrace get stackTrace; |
+ |
+ /// The name of the group within which this test is running. |
+ String get currentGroup; |
+ |
+ /// The time the test case started running. |
+ /// |
+ /// `null` if the test hasn't yet begun running. |
+ DateTime get startTime; |
+ |
+ /// The amount of time the test case took. |
+ /// |
+ /// `null` if the test hasn't finished running. |
+ Duration get runningTime; |
+ |
+ /// Whether this test is enabled. |
+ /// |
+ /// Disabled tests won't be run. |
+ bool get enabled; |
+ |
+ /// Whether this test case has finished running. |
+ bool get isComplete => !enabled || result != null; |
+} |
+ |
/// The type used for functions that can be used to build up error reports |
/// upon failures in [expect]. |
typedef String ErrorFormatter( |
@@ -99,3 +253,6 @@ String _defaultFailFormatter( |
if (reason != null) description.add(reason).add('\n'); |
return description.toString(); |
} |
+ |
+// from html_configuration |
+void useHtmlConfiguration([bool isLayoutTest = false]) { } |