Skip to content

Commit 8f37fbd

Browse files
authored
feat: add ExitTestEvent to indicate the process has exited (#6)
1 parent 7244ac7 commit 8f37fbd

File tree

5 files changed

+62
-2
lines changed

5 files changed

+62
-2
lines changed

lib/src/models/test_event.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ abstract class TestEvent {
3636
return TestDoneEvent.fromJson(json);
3737
case 'done':
3838
return DoneTestEvent.fromJson(json);
39+
case 'exit':
40+
return ExitTestEvent.fromJson(json);
3941
default:
4042
throw UnsupportedError('Unsupported type: $type');
4143
}
@@ -331,6 +333,24 @@ class DoneTestEvent extends TestEvent {
331333
final bool? success;
332334
}
333335

336+
/// {@template test_exit_event}
337+
/// An event emitted when a test completes.
338+
/// The [exitCode] attribute indicates the result of the test process.
339+
/// {@endtemplate}
340+
@JsonSerializable()
341+
class ExitTestEvent extends TestEvent {
342+
/// {@macro test_exit_event}
343+
const ExitTestEvent({required int time, required this.exitCode})
344+
: super(type: 'exit', time: time);
345+
346+
/// {@macro test_exit_event}
347+
factory ExitTestEvent.fromJson(Map<String, dynamic> json) =>
348+
_$ExitTestEventFromJson(json);
349+
350+
/// The exit code associated with the test process.
351+
final int exitCode;
352+
}
353+
334354
/// {@template test_suite}
335355
/// A test suite corresponding to a loaded test file.
336356
/// The suite's ID is unique in the context of this test run.

lib/src/models/test_event.g.dart

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/src/very_good_test_runner.dart

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ Stream<TestEvent> _runTestProcess(
7878
late Future<Process> processFuture;
7979

8080
Future<void> _onListen() async {
81+
final stopwatch = Stopwatch()..start();
8182
processFuture = processRunner();
8283
final process = await processFuture;
8384
final errors = process.stderr.map((e) => utf8.decode(e).trim());
@@ -86,8 +87,22 @@ Stream<TestEvent> _runTestProcess(
8687
testEventSubscription = testEvents.listen(
8788
controller.add,
8889
onError: controller.addError,
89-
onDone: controller.close,
9090
);
91+
92+
final exitCode = await process.exitCode;
93+
stopwatch.stop();
94+
await Future.wait([
95+
errorSubscription.cancel(),
96+
testEventSubscription.cancel(),
97+
]);
98+
if (controller.isClosed) return;
99+
controller.add(
100+
ExitTestEvent(
101+
time: stopwatch.elapsedMilliseconds,
102+
exitCode: exitCode,
103+
),
104+
);
105+
await controller.close();
91106
}
92107

93108
Future<void> _onCancel() async {

test/src/models/test_event_test.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@ void main() {
143143

144144
expect(TestEvent.fromJson(json), isA<DoneTestEvent>());
145145
});
146+
147+
test('returns ExitTestEvent when type is exit', () {
148+
final json = {'exitCode': 0, 'type': 'exit', 'time': 4034};
149+
150+
expect(TestEvent.fromJson(json), isA<ExitTestEvent>());
151+
});
146152
});
147153
});
148154
}

test/src/very_good_test_runner_test.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ void main() {
4747
).thenAnswer((_) async => process);
4848
when(() => process.stdout).thenAnswer((_) => stdoutController.stream);
4949
when(() => process.stderr).thenAnswer((_) => stderrController.stream);
50+
when(() => process.exitCode).thenAnswer((_) async => 0);
5051
when(process.kill).thenReturn(true);
5152
});
5253

@@ -158,6 +159,7 @@ void main() {
158159
).thenAnswer((_) async => process);
159160
when(() => process.stdout).thenAnswer((_) => stdoutController.stream);
160161
when(() => process.stderr).thenAnswer((_) => stderrController.stream);
162+
when(() => process.exitCode).thenAnswer((_) async => 0);
161163
when(process.kill).thenReturn(true);
162164
});
163165

@@ -246,6 +248,8 @@ void main() {
246248
});
247249

248250
test('emits correct stream of TestEvents', () async {
251+
final completer = Completer<int>();
252+
when(() => process.exitCode).thenAnswer((_) => completer.future);
249253
final rawEvents = [
250254
{
251255
'protocolVersion': '0.1.1',
@@ -740,7 +744,6 @@ void main() {
740744
(element) => utf8.encode(json.encode(element)),
741745
);
742746
await stdoutController.addStream(Stream.fromIterable(encodedEvents));
743-
await stdoutController.close();
744747
expect(
745748
events,
746749
equals([
@@ -788,6 +791,9 @@ void main() {
788791
isA<DoneTestEvent>(),
789792
]),
790793
);
794+
completer.complete(0);
795+
await Future<void>.delayed(Duration.zero);
796+
expect(events.last, isA<ExitTestEvent>());
791797
unawaited(subscription.cancel());
792798
});
793799
});

0 commit comments

Comments
 (0)