| // Copyright (c) 2021, 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. | |
| import 'dart:async'; | |
| import 'package:stack_trace/stack_trace.dart'; | |
| import 'src/backend/closed_exception.dart'; | |
| import 'src/backend/invoker.dart'; | |
| import 'src/backend/stack_trace_formatter.dart'; | |
| export 'src/backend/test_failure.dart' show TestFailure; | |
| export 'src/scaffolding/utils.dart' show pumpEventQueue; | |
| final class TestHandle { | |
| /// Returns handle for the currently running test. | |
| /// | |
| /// This must be called from within the zone that the test is running in. If | |
| /// the current zone is not a test's zone throws [OutsideTestException]. | |
| static TestHandle get current { | |
| final invoker = Invoker.current; | |
| if (invoker == null) throw OutsideTestException(); | |
| return TestHandle._( | |
| invoker, | |
| StackTraceFormatter.current ?? _defaultFormatter, | |
| ); | |
| } | |
| static final _defaultFormatter = StackTraceFormatter(); | |
| final Invoker _invoker; | |
| final StackTraceFormatter _stackTraceFormatter; | |
| TestHandle._(this._invoker, this._stackTraceFormatter); | |
| String get name => _invoker.liveTest.test.name; | |
| /// Whether this test has already completed successfully. | |
| /// | |
| /// If a callback originating from a test case is invoked after the test has | |
| /// already passed it may be an indication of a test that fails to wait for | |
| /// all work to be finished, or of an asynchronous callback that is called | |
| /// more times or later than expected. | |
| bool get shouldBeDone => _invoker.liveTest.state.shouldBeDone; | |
| /// Marks this test as skipped. | |
| /// | |
| /// A skipped test may still fail if any exception is thrown, including | |
| /// uncaught asynchronous errors. | |
| void markSkipped(String message) { | |
| if (_invoker.closed) throw ClosedException(); | |
| _invoker.skip(message); | |
| } | |
| /// Indicates that this test should not be considered done until the returned | |
| /// [OutstandingWork] is marked as complete. | |
| /// | |
| /// The test may time out before the outstanding work completes. | |
| OutstandingWork markPending() { | |
| if (_invoker.closed) throw ClosedException(); | |
| return OutstandingWork._(_invoker, Zone.current); | |
| } | |
| /// Converts [stackTrace] to a [Chain] according to the current test's | |
| /// configuration. | |
| Chain formatStackTrace(StackTrace stackTrace) => | |
| _stackTraceFormatter.formatStackTrace(stackTrace); | |
| } | |
| final class OutstandingWork { | |
| final Invoker _invoker; | |
| final Zone _zone; | |
| var _isComplete = false; | |
| OutstandingWork._(this._invoker, this._zone) { | |
| _invoker.addOutstandingCallback(); | |
| } | |
| void complete() { | |
| if (_isComplete) return; | |
| _isComplete = true; | |
| _zone.run(_invoker.removeOutstandingCallback); | |
| } | |
| } | |
| final class OutsideTestException implements Exception {} |