import 'dart:convert'; import 'dart:io'; import 'package:pipe/pipe.dart'; import 'package:pipe/src/cli.dart'; import 'package:test/test.dart'; /// Collects what a command writes to stdout. class _CapturedStdout implements Stdout { final StringBuffer buffer = StringBuffer(); @override void write(Object? object) => buffer.write(object); @override void writeln([Object? object = '']) => buffer.writeln(object); @override dynamic noSuchMethod(Invocation invocation) => null; } Future<(int?, String)> _run(List args) async { final out = _CapturedStdout(); final code = await IOOverrides.runZoned( () => PipeRunner().run(args), stdout: () => out, ); return (code, out.buffer.toString()); } const String _fixture = 'test/fixtures/stuck_loading'; void main() { late String baseline; setUpAll(() async { final dir = Directory.systemTemp.createTempSync('pipe-subset'); baseline = '${dir.path}/baseline.json'; final (code, _) = await _run([ 'check', _fixture, '--write-baseline', baseline, '-c', '1', ]); expect(code, 0); }); test('verify --rule does not call other rules\' findings resolved', () async { // Only dead-handler ran, so accepted findings from every other rule were // unchecked, not fixed. Comparing against the whole baseline reported each // of them as RESOLVED - a false claim about someone's fixes. final entries = decodeBaselineEntries(File(baseline).readAsStringSync()); expect( entries.map((entry) => entry.rule).toSet(), hasLength(greaterThan(1)), reason: 'the control needs findings from more than the selected rule', ); final (_, output) = await _run([ 'verify', _fixture, '--baseline', baseline, '--rule', ruleDeadHandler, '--format', 'json', '-c', '1', ]); final report = jsonDecode(output) as Map; expect(report['resolved'], 0); expect(report['new'], 0); expect( report['baselineTotal'], entries.where((entry) => entry.rule == ruleDeadHandler).length, ); }); for (final narrowing in [ ['--rule', ruleDeadHandler], ['--limit', '3'], ]) { test('--write-baseline refuses ${narrowing.first}', () async { final target = '${File(baseline).parent.path}/subset.json'; await expectLater( _run([ 'check', _fixture, ...narrowing, '--write-baseline', target, '-c', '1', ]), throwsA( isA().having( (error) => error.toString(), 'message', contains('complete scan'), ), ), ); expect(File(target).existsSync(), isFalse); }); } }