Skip to content

Commit

Permalink
. r F highlight error text in command line reporter
Browse files Browse the repository at this point in the history
  • Loading branch information
yelmuratoff committed May 17, 2024
1 parent 8b49bcf commit 9c210f4
Show file tree
Hide file tree
Showing 19 changed files with 176 additions and 138 deletions.
2 changes: 1 addition & 1 deletion example/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ void main() {
Approvals.verifyAll(
[3, 5, 15],
options: const Options(
comparator: IDEComparator(),
reporter: DiffReporter(),
deleteReceivedFile: true,
),
processor: (items) => fizzBuzz(items).toString(),
Expand Down
3 changes: 2 additions & 1 deletion example/verify_methods/verify/verify_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import 'package:test/test.dart';

void main() {
test('verify method', () {
const String response = '{"result": "success", "data": {"id": 1, "name": "Item"}}';
const String response =
'{"result": "success", "data": {"id": 1, "name": "Item"}}';

Approvals.verify(
response,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ void main() {
Approvals.verifyAsJson(
jsonItem,
options: const Options(
deleteReceivedFile: true, // Automatically delete the received file after the test.
approveResult: true, // Approve the result automatically. You can remove this property after the approved file is created.
deleteReceivedFile:
true, // Automatically delete the received file after the test.
approveResult:
true, // Approve the result automatically. You can remove this property after the approved file is created.
),
);
});
Expand Down
14 changes: 9 additions & 5 deletions lib/approval_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ part 'src/writers/approval_text_writer.dart';

part 'src/core/logger/logger.dart';
part 'src/core/utils/utils.dart';
part 'src/core/reporter.dart';
part 'src/core/options.dart';
part 'src/core/approval_writer.dart';
part 'src/core/enums/comporator_ide.dart';
Expand All @@ -27,12 +28,15 @@ part 'src/namer/namer.dart';
part 'src/core/approval_number.dart';
part 'src/namer/file_namer_options.dart';

part 'src/reporters/comparator.dart';
part 'src/reporters/command_line_comparator.dart';
part 'src/reporters/ide_comparator.dart';
part 'src/reporters/diff_info.dart';
part 'src/reporters/diff_tools.dart';
part 'src/core/comparator.dart';
part 'src/comparator/file_comparator.dart';
part 'src/reporters/diff_tool/diff_info.dart';
part 'src/reporters/diff_tool/diff_tools.dart';

part 'src/exceptions/doesnt_match_exception.dart';
part 'src/exceptions/command_line_comparator_exception.dart';
part 'src/exceptions/ide_comparator_exception.dart';

part 'src/reporters/command_line/command_line_reporter.dart';
part 'src/reporters/diff_tool/diff_tool_reporter.dart';
part 'src/reporters/command_line/colorize.dart';
15 changes: 7 additions & 8 deletions lib/src/approvals.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,19 @@ class Approvals {
}

// Check if received file matches the approved file
final bool isFilesMatch =
ApprovalUtils.filesMatch(namer.approved, namer.received);
final bool isFilesMatch = options.comparator.compare(
approvedPath: namer.approved,
receivedPath: namer.received,
isLogError: options.logErrors,
);

// Log results and throw exception if files do not match
if (!isFilesMatch) {
options.comparator.compare(
approvedPath: namer.approved,
receivedPath: namer.received,
isLogError: options.logErrors,
);
options.reporter.report(namer.approved, namer.received);
throw DoesntMatchException(
'Test failed: ${namer.approved} does not match ${namer.received}.\n - Approved file path: ${namer.approved}\n - Received file path: ${namer.received}',
);
} else if (isFilesMatch) {
} else {
if (options.logResults) {
ApprovalLogger.success(
'Test passed: [${namer.approvedFileName}] matches [${namer.receivedFileName}]\n- Approved file path: ${namer.approved}\n- Received file path: ${namer.received}',
Expand Down
31 changes: 31 additions & 0 deletions lib/src/comparator/file_comparator.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
part of '../../approval_tests.dart';

/// A class `FileComparator` that implements the `Comparator` interface.
/// This class is used to compare the content of two files.
final class FileComparator implements Comparator {
const FileComparator();

@override
bool compare({
required String approvedPath,
required String receivedPath,
bool isLogError = true,
}) {
try {
final approved = ApprovalUtils.readFile(path: approvedPath)
.replaceAll('\r\n', '\n')
.trim();
final received = ApprovalUtils.readFile(path: receivedPath)
.replaceAll('\r\n', '\n')
.trim();

// Return true if contents of both files match exactly
return approved.compareTo(received) == 0;
} catch (e) {
if (isLogError) {
ApprovalLogger.exception(e.toString());
}
rethrow;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ abstract interface class Comparator {
const Comparator();

/// A method named `compare` for comparing two files.
Future<void> compare({
bool compare({
required String approvedPath,
required String receivedPath,
bool isLogError = true,
Expand Down
4 changes: 3 additions & 1 deletion lib/src/core/extensions/approval_string_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ extension StringExtensions on String {
}) {
final regExp = RegExp(matchingPattern);
return replaceAllMapped(
regExp, (match) => replacementProvider(match.group(0)!),);
regExp,
(match) => replacementProvider(match.group(0)!),
);
}
}
6 changes: 5 additions & 1 deletion lib/src/core/options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ class Options {
/// A final variable `comparator` of type `Comparator` used to compare the approved and received files.
final Comparator comparator;

/// A final variable `reporter` of type `Reporter` used to report the comparison results.
final Reporter reporter;

/// A final bool variable `approveResult` used to determine if the result should be approved after the test.
final bool approveResult;

Expand All @@ -27,7 +30,8 @@ class Options {
const Options({
this.scrubber = const ScrubNothing(),
this.approveResult = false,
this.comparator = const CommandLineComparator(),
this.comparator = const FileComparator(),
this.reporter = const CommandLineReporter(),
this.deleteReceivedFile = false,
this.namer,
this.logErrors = true,
Expand Down
6 changes: 6 additions & 0 deletions lib/src/core/reporter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
part of '../../approval_tests.dart';

/// `Reporter` is an abstract class for reporting the comparison results.
abstract interface class Reporter {
void report(String approvedPath, String receivedPath);
}
18 changes: 0 additions & 18 deletions lib/src/core/utils/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,24 +54,6 @@ final class ApprovalUtils {

static String lines(int count) => List.filled(count, '=').join();

// Helper private method to check if contents of two files match
static bool filesMatch(String approvedPath, String receivedPath) {
try {
// Read contents of the approved and received files
final approved = ApprovalUtils.readFile(path: approvedPath)
.replaceAll('\r\n', '\n')
.trim();
final received = ApprovalUtils.readFile(path: receivedPath)
.replaceAll('\r\n', '\n')
.trim();

// Return true if contents of both files match exactly
return approved.compareTo(received) == 0;
} catch (_) {
rethrow;
}
}

static void deleteFile(String path) {
try {
final File file = File(path);
Expand Down
19 changes: 19 additions & 0 deletions lib/src/reporters/command_line/colorize.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
part of '../../../approval_tests.dart';

enum _LogColorStyles { red, bgRed }

class _Colorize {
static const String esc = "\u{1B}[";
final String text;

const _Colorize(this.text);

_Colorize apply(_LogColorStyles style) {
final appliedText =
"$esc${style == _LogColorStyles.red ? '38;2;222;121;121' : '41'}m$text${esc}0m";
return _Colorize(appliedText);
}

@override
String toString() => text;
}
60 changes: 60 additions & 0 deletions lib/src/reporters/command_line/command_line_reporter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
part of '../../../approval_tests.dart';

/// `CommandLineReporter` is a class for reporting the comparison results using the command line.
class CommandLineReporter implements Reporter {
const CommandLineReporter();

@override
void report(String approvedPath, String receivedPath, {String? message}) {
try {
final String approvedContent = ApprovalUtils.readFile(path: approvedPath);
final String receivedContent = ApprovalUtils.readFile(path: receivedPath);

final StringBuffer buffer = StringBuffer(message ?? "Differences:\n");
final List<String> approvedLines = approvedContent.split('\n');
final List<String> receivedLines = receivedContent.split('\n');

final int maxLines = max(approvedLines.length, receivedLines.length);
for (int i = 0; i < maxLines; i++) {
final String approvedLine =
i < approvedLines.length ? approvedLines[i] : "";
final String receivedLine =
i < receivedLines.length ? receivedLines[i] : "";

if (approvedLine != receivedLine) {
buffer.writeln(
'${ApprovalUtils.lines(20)} Difference at line ${i + 1} ${ApprovalUtils.lines(20)}',
);
buffer.writeln(
'Approved file: ${_highlightDifference(approvedLine, receivedLine)}',
);
buffer.writeln(
'Received file: ${_highlightDifference(receivedLine, approvedLine)}',
);
}
}

if (buffer.isNotEmpty) {
final String reportMessage = buffer.toString();
ApprovalLogger.exception(reportMessage);
}
} catch (e) {
rethrow;
}
}

String _highlightDifference(String line1, String line2) {
final int minLength = min(line1.length, line2.length);
final StringBuffer highlighted = StringBuffer();

for (int i = 0; i < minLength; i++) {
if (line1[i] != line2[i]) {
highlighted.write(_Colorize(line1[i]).apply(_LogColorStyles.bgRed));
} else {
highlighted.write(_Colorize(line1[i]).apply(_LogColorStyles.red));
}
}

return highlighted.toString();
}
}
50 changes: 0 additions & 50 deletions lib/src/reporters/command_line_comparator.dart

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
part of '../../../approval_tests.dart';
part of '../../../../approval_tests.dart';

/// `DiffInfo` is a class for storing information about a diff tool.
class DiffInfo {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,44 +1,27 @@
part of '../../approval_tests.dart';
part of '../../../approval_tests.dart';

/// `IDEComparator` is a class for comparing files using an `IDE`.
///
/// Available IDEs:
/// - `Visual Studio Code`
/// - `Android Studio`
final class IDEComparator extends Comparator {
/// `DiffReporter` is a class for reporting the comparison results using a `Diff Tool`.
class DiffReporter implements Reporter {
final ComparatorIDE ide;
final DiffInfo? customDiffInfo;

const IDEComparator({
const DiffReporter({
this.ide = ComparatorIDE.vsCode,
this.customDiffInfo,
});

@override
Future<void> compare({
required String approvedPath,
required String receivedPath,
bool isLogError = true,
}) async {
Future<void> report(String approvedPath, String receivedPath) async {
final DiffInfo diffInfo = _diffInfo;
try {
final File approvedFile = File(approvedPath);
final File receivedFile = File(receivedPath);

if (!_fileExists(approvedFile) || !_fileExists(receivedFile)) {
_throwFileException(
'Files not found for comparison. Please check the paths: \n\n Approved file path: $approvedPath, \n\n Received file path: $receivedPath.',
);
}
final DiffInfo diffInfo = _diffInfo;

await Process.run(
diffInfo.command,
[diffInfo.arg, approvedPath, receivedPath],
);
} catch (e, st) {
throw IDEComparatorException(
message:
'Error during comparison via ${ide.name}. Please try restart your IDE.',
'Error during comparison via ${ide.name}. Please try check path to IDE. \n Current path: ${diffInfo.command}.',
exception: e,
stackTrace: st,
);
Expand Down Expand Up @@ -67,14 +50,4 @@ final class IDEComparator extends Comparator {
}
}
}

bool _fileExists(File file) => file.existsSync();

void _throwFileException(String message) {
throw IDEComparatorException(
message: message,
exception: null,
stackTrace: StackTrace.current,
);
}
}
Loading

0 comments on commit 9c210f4

Please sign in to comment.