import 'dart:convert'; import 'dart:io'; import 'package:args/command_runner.dart'; import 'package:path/path.dart' as p; import 'package:pipe/src/cli.dart'; import 'package:test/test.dart'; void main() { test( 'a second project path is a usage error, not silently dropped', () async { // `pipe check a b` used to analyse only `a` and report as if both ran. await expectLater( PipeRunner().run(['check', 'test/fixtures/stuck_loading', 'lib']), throwsA( isA().having( (e) => e.message, 'message', contains('expected one project path, got 2'), ), ), ); }, ); test('recall finds the pipe manifest from outside the repo', () { // The default used to be cwd-relative, so `pipe recall` failed anywhere // but the pipe checkout. final elsewhere = Directory.systemTemp.createTempSync('pipe-recall-cwd'); final script = p.join(Directory.current.path, 'bin', 'pipe.dart'); final found = defaultRecallManifest( cwd: elsewhere.path, searchFrom: [script], ); expect( p.equals(found, p.join(Directory.current.path, 'recall/manifest.json')), isTrue, reason: found, ); }); test('recall prefers a manifest in the working directory', () { final temp = Directory.systemTemp.createTempSync('pipe-recall-local'); final local = File(p.join(temp.path, 'recall', 'manifest.json')) ..createSync(recursive: true) ..writeAsStringSync('[]'); expect( defaultRecallManifest(cwd: temp.path, searchFrom: const []), local.path, ); }); test('guide --yams writes the baseline even when yams fails, and does not ' 'hang on a chatty yams', () async { // A fake yams that floods stdout (more than a pipe buffer) and then fails. // Before: pipe read only stderr, so the child blocked on a full stdout and // the run hung; and the yams failure returned before --write-baseline ran. final temp = Directory.systemTemp.createTempSync('pipe-fake-yams'); final fake = File(p.join(temp.path, 'yams')) ..writeAsStringSync( '#!/bin/sh\n' 'cat >/dev/null\n' 'head -c 1048576 /dev/zero | tr "\\\\0" x\n' 'echo "fake yams down" >&2\n' 'exit 3\n', ); await Process.run('chmod', ['+x', fake.path]); final baseline = p.join(temp.path, 'baseline.json'); final result = await Process.run( Platform.resolvedExecutable, [ 'bin/pipe.dart', 'guide', 'test/fixtures/stuck_loading', '--yams', '--write-baseline', baseline, '-c', '1', ], environment: {'PATH': '${temp.path}:/usr/bin:/bin'}, ).timeout(const Duration(minutes: 2)); expect(result.exitCode, 1, reason: '${result.stderr}'); expect(result.stderr as String, contains('fake yams down')); expect(File(baseline).existsSync(), isTrue); }); test('a written baseline records its root relative to the file', () async { // It used to store the absolute project path, so a committed baseline // leaked one machine's home directory and churned on every checkout. final temp = Directory.systemTemp.createTempSync('pipe-baseline-root'); final baseline = p.join(temp.path, 'baseline.json'); final result = await Process.run(Platform.resolvedExecutable, [ 'bin/pipe.dart', 'check', 'test/fixtures/stuck_loading', '--write-baseline', baseline, '-c', '1', ]); expect(result.exitCode, 0, reason: '${result.stderr}'); final root = (jsonDecode(File(baseline).readAsStringSync()) as Map)['root']; expect(p.isAbsolute(root as String), isFalse, reason: root); expect( p.equals( p.normalize(p.join(temp.path, root)), p.absolute('test/fixtures/stuck_loading'), ), isTrue, reason: root, ); }); }