import 'dart:convert'; import 'dart:io'; import 'package:oto/cli/commands/command_validate.dart'; import 'package:test/test.dart'; void main() { const validYaml = ''' commands: - command: Print id: hello param: message: hi pipeline: id: main workflow: - exe: hello '''; const invalidYaml = ''' commands: - command: Print id: hello param: message: hi pipeline: id: main workflow: - exe: non_existent_id '''; test('CommandValidateCli shouldPrintExecuteLog behavior', () { final command = CommandValidateCli(); expect(command.shouldPrintExecuteLog(['--json']), isFalse); expect( command.shouldPrintExecuteLog(['--json', '-f', 'file.yaml']), isFalse); expect(command.shouldPrintExecuteLog(['-f', 'file.yaml']), isTrue); }); test('CommandValidateCli json output for valid yaml', () async { final file = File('${Directory.systemTemp.path}/oto_validate_valid_test.yaml'); file.writeAsStringSync(validYaml); final lines = []; final command = CommandValidateCli(printString: (value) async { lines.add(value); }); try { final oldExitCode = exitCode; await command.execute(['-f', file.path, '--json']); final jsonStr = lines.join('\n'); final decoded = jsonDecode(jsonStr) as Map; expect(decoded['schemaVersion'], 1); expect(decoded['type'], 'yamlValidation'); expect(decoded['valid'], isTrue); expect(decoded['exitCode'], 0); expect(exitCode, 0); // restore exitCode exitCode = oldExitCode; } finally { if (file.existsSync()) { file.deleteSync(); } } }); test('CommandValidateCli json output for invalid yaml', () async { final file = File('${Directory.systemTemp.path}/oto_validate_invalid_test.yaml'); file.writeAsStringSync(invalidYaml); final lines = []; final command = CommandValidateCli(printString: (value) async { lines.add(value); }); try { final oldExitCode = exitCode; await command.execute(['-f', file.path, '--json']); final jsonStr = lines.join('\n'); final decoded = jsonDecode(jsonStr) as Map; expect(decoded['schemaVersion'], 1); expect(decoded['type'], 'yamlValidation'); expect(decoded['valid'], isFalse); expect(decoded['phase'], 'Validate Pipeline'); expect(decoded['exitCode'], 10); expect(exitCode, 10); // restore exitCode exitCode = oldExitCode; } finally { if (file.existsSync()) { file.deleteSync(); } } }); test('CommandValidateCli human format output for valid/invalid yaml', () async { final validFile = File('${Directory.systemTemp.path}/oto_validate_human_valid.yaml'); validFile.writeAsStringSync(validYaml); final invalidFile = File('${Directory.systemTemp.path}/oto_validate_human_invalid.yaml'); invalidFile.writeAsStringSync(invalidYaml); try { final linesValid = []; final commandValid = CommandValidateCli(printString: (value) async { linesValid.add(value); }); final oldExitCode1 = exitCode; await commandValid.execute(['-f', validFile.path]); expect(linesValid.join('\n'), contains('Valid YAML.')); expect(exitCode, 0); exitCode = oldExitCode1; final linesInvalid = []; final commandInvalid = CommandValidateCli(printString: (value) async { linesInvalid.add(value); }); final oldExitCode2 = exitCode; await commandInvalid.execute(['-f', invalidFile.path]); expect(linesInvalid.join('\n'), contains('Invalid YAML: [Validate Pipeline]')); expect(exitCode, 10); exitCode = oldExitCode2; } finally { if (validFile.existsSync()) validFile.deleteSync(); if (invalidFile.existsSync()) invalidFile.deleteSync(); } }); test('CommandValidateCli missing file returns validation json and exit code', () async { final lines = []; final command = CommandValidateCli(printString: (value) async { lines.add(value); }); final oldExitCode = exitCode; await command.execute(['-f', 'non_existent_file_path_12345.yaml', '--json']); final jsonStr = lines.join('\n'); final decoded = jsonDecode(jsonStr) as Map; expect(decoded['schemaVersion'], 1); expect(decoded['type'], 'yamlValidation'); expect(decoded['valid'], isFalse); expect(decoded['phase'], 'Read YAML file'); expect(decoded['message'], contains('There are no files in path')); expect(decoded['exitCode'], 10); expect(exitCode, 10); // restore exitCode exitCode = oldExitCode; }); test( 'actual bin validate --json output has parseable json and no execute logs', () async { final file = File('${Directory.systemTemp.path}/oto_validate_bin_test.yaml'); file.writeAsStringSync(validYaml); try { final result = await Process.run( 'dart', ['run', 'bin/main.dart', 'validate', '-f', file.path, '--json'], ); expect(result.exitCode, 0, reason: result.stderr.toString()); final stdoutStr = result.stdout.toString().trim(); final decoded = jsonDecode(stdoutStr) as Map; expect(decoded['schemaVersion'], 1); expect(decoded['type'], 'yamlValidation'); expect(decoded['valid'], isTrue); expect(decoded['exitCode'], 0); expect(stdoutStr, isNot(contains('Execute command:'))); expect(stdoutStr, isNot(contains('Usage:'))); } finally { if (file.existsSync()) { file.deleteSync(); } } }); }