Skip to content

Commit

Permalink
fix(coverde): platform-aware path handling (#82)
Browse files Browse the repository at this point in the history
* fix(coverde): properly handle source paths

* test(coverde): update tests

* test(coverde): use inline fixtures

* test(coverde): path-context-based trace file fixture

* chore: ignore word for spell check

* docs(coverde): update changelog
  • Loading branch information
mrverdant13 authored Nov 16, 2023
1 parent ec04270 commit 0a54537
Show file tree
Hide file tree
Showing 32 changed files with 579 additions and 5,096 deletions.
4 changes: 4 additions & 0 deletions packages/coverde_cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Unreleased

- **FIX**: use platform-dependent path handling (#82).

## 0.2.0+2

- **FEAT**: optional prefix for filtered paths (#69).
Expand Down
7 changes: 5 additions & 2 deletions packages/coverde_cli/lib/src/commands/filter/filter.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:args/command_runner.dart';
import 'package:coverde/src/entities/trace_file.dart';
import 'package:coverde/src/utils/command.dart';
import 'package:coverde/src/utils/path.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:universal_io/io.dart';

/// {@template filter_cmd}
Expand Down Expand Up @@ -172,7 +172,10 @@ If an absolute path is found in the coverage trace file, the process will fail.'
? fileCovData.raw
: fileCovData.raw.replaceFirst(
RegExp(r'^SF:(.*)$', multiLine: true),
'SF:${path.join(pathsParent, fileCovData.source.path)}',
'SF:${path.joinAll([
...path.split(pathsParent),
fileCovData.source.path,
])}',
);
acceptedSrcFilesRawData.add(raw);
}
Expand Down
16 changes: 9 additions & 7 deletions packages/coverde_cli/lib/src/commands/report/report.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import 'package:coverde/src/assets/sort_alpha.png.asset.dart';
import 'package:coverde/src/assets/sort_numeric.png.asset.dart';
import 'package:coverde/src/entities/trace_file.dart';
import 'package:coverde/src/utils/command.dart';
import 'package:coverde/src/utils/path.dart';
import 'package:io/ansi.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:process/process.dart';
import 'package:universal_io/io.dart';

Expand Down Expand Up @@ -120,9 +120,13 @@ Generate the coverage report inside $_outputHelpValue from the $_inputHelpValue
optionKey: inputOption,
optionName: 'input trace file',
);
final _reportDirPath = checkOption(
optionKey: outputOption,
optionName: 'output report folder',
final _reportDirPath = path.joinAll(
path.split(
checkOption(
optionKey: outputOption,
optionName: 'output report folder',
),
),
);
final mediumString = checkOption(
optionKey: mediumOption,
Expand Down Expand Up @@ -199,9 +203,7 @@ Generate the coverage report inside $_outputHelpValue from the $_inputHelpValue
..createSync(recursive: true)
..writeAsBytesSync(sortNumericPngBytes);

final reportIndexAbsPath = path
.join(reportDirAbsPath, 'index.html')
.replaceAll(RegExp(r'(\/|\\)'), path.separator);
final reportIndexAbsPath = path.joinAll([reportDirAbsPath, 'index.html']);

_out
..writeln(covTree)
Expand Down
5 changes: 3 additions & 2 deletions packages/coverde_cli/lib/src/entities/cov_base.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// cspell:words nbsp

import 'package:coverde/src/assets/folder_report_row_template.html.asset.dart';
import 'package:coverde/src/utils/path.dart';
import 'package:html/dom.dart';
import 'package:io/ansi.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:universal_io/io.dart';

/// # Computable Coverage Entity
Expand Down Expand Up @@ -86,10 +86,11 @@ abstract class CovElement extends CovComputable {
required double medium,
required double high,
}) {
relativePath = path.url.joinAll(path.split(relativePath));
final row = _folderReportRowTemplate.clone(true);
final suffix = getClassSuffix(medium: medium, high: high);
final link = source is Directory
? path.join(relativePath, 'index.html')
? path.url.join(relativePath, 'index.html')
: '$relativePath.html';
row.querySelector('.coverFileAnchor')
?..attributes['href'] = link
Expand Down
15 changes: 8 additions & 7 deletions packages/coverde_cli/lib/src/entities/cov_dir.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import 'package:coverde/src/assets/sort_alpha.png.asset.dart';
import 'package:coverde/src/assets/sort_numeric.png.asset.dart';
import 'package:coverde/src/entities/cov_base.dart';
import 'package:coverde/src/entities/cov_file.dart';
import 'package:coverde/src/utils/path.dart';
import 'package:html/dom.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:universal_io/io.dart';

/// {@template cov_dir}
Expand Down Expand Up @@ -210,9 +210,10 @@ class CovDir extends CovElement {
final folderReport = folderReportTemplate.clone(true);

final topLevelDirRelPath =
List.filled(reportRelDepth, '..').fold('', path.join);
final topLevelReportRelPath = path.join(topLevelDirRelPath, 'index.html');
final topLevelCssRelPath = path.join(
path.url.joinAll(List.filled(reportRelDepth, '..'));
final topLevelReportRelPath =
path.url.join(topLevelDirRelPath, 'index.html');
final topLevelCssRelPath = path.url.join(
topLevelDirRelPath,
reportStyleCssFilename,
);
Expand All @@ -224,11 +225,11 @@ class CovDir extends CovElement {
final reportFileAbsPath = path.join(reportDirAbsPath, 'index.html');

final title = 'Coverage Report - $traceFileName';
final sortAlphaIconPath = path.join(
final sortAlphaIconPath = path.url.join(
topLevelDirRelPath,
sortAlphaPngFilename,
);
final sortNumericIconPath = path.join(
final sortNumericIconPath = path.url.join(
topLevelDirRelPath,
sortNumericPngFilename,
);
Expand All @@ -245,7 +246,7 @@ class CovDir extends CovElement {
folderReport.querySelector('.sortNumeric')?.attributes['src'] =
sortNumericIconPath;
folderReport.querySelector('.currentDirPath')?.nodes.last.text =
' - ${source.path}';
' - ${path.url.joinAll(path.split(source.path))}';
folderReport.querySelector('.traceFileName')?.text = traceFileName;
folderReport.querySelector('.linesHit')?.text = '$linesHit';
folderReport.querySelector('.linesFound')?.text = '$linesFound';
Expand Down
20 changes: 8 additions & 12 deletions packages/coverde_cli/lib/src/entities/cov_file.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import 'package:coverde/src/assets/report_style.css.asset.dart';
import 'package:coverde/src/entities/cov_base.dart';
import 'package:coverde/src/entities/cov_file_format.exception.dart';
import 'package:coverde/src/entities/cov_line.dart';
import 'package:coverde/src/utils/path.dart';
import 'package:html/dom.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:universal_io/io.dart';

/// {@template cov_file}
Expand Down Expand Up @@ -47,18 +47,13 @@ class CovFile extends CovElement {
.replaceAll(sourceFileTag, '')
.trim();

final sourceFile = path.canonicalize(
[
'.',
...sourcePath().split(RegExp(r'(\\|\/)')),
].reduce(path.join),
);
final sourceFilePath = path.joinAll(path.split(sourcePath()));

final covLines =
dataLines.where((l) => l.startsWith(lineDataTag)).map(CovLine.parse);

return CovFile(
source: File(sourceFile),
source: File(sourceFilePath),
raw: data,
covLines: covLines,
);
Expand Down Expand Up @@ -134,10 +129,11 @@ class CovFile extends CovElement {
final fileReport = fileReportTemplate.clone(true);

final topLevelDirRelPath = (reportRelDepth > 1)
? List.filled(reportRelDepth - 1, '..').reduce(path.join)
? path.url.joinAll(List.filled(reportRelDepth - 1, '..'))
: '.';
final topLevelReportRelPath = path.join(topLevelDirRelPath, 'index.html');
final topLevelCssRelPath = path.join(
final topLevelReportRelPath =
path.url.join(topLevelDirRelPath, 'index.html');
final topLevelCssRelPath = path.url.join(
topLevelDirRelPath,
reportStyleCssFilename,
);
Expand All @@ -149,7 +145,7 @@ class CovFile extends CovElement {

{
final title = 'Coverage Report - $traceFileName';
final currentDirPath = source.parent.path;
final currentDirPath = path.url.joinAll(path.split(source.parent.path));
final fileName = path.basename(source.path);
final suffix = getClassSuffix(medium: medium, high: high);

Expand Down
4 changes: 0 additions & 4 deletions packages/coverde_cli/lib/src/utils/path.dart

This file was deleted.

55 changes: 39 additions & 16 deletions packages/coverde_cli/test/src/commands/check/check_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,13 @@ import 'package:args/command_runner.dart';
import 'package:coverde/src/commands/check/check.dart';
import 'package:coverde/src/commands/check/min_coverage.exception.dart';
import 'package:coverde/src/entities/trace_file.dart';
import 'package:coverde/src/utils/path.dart';
import 'package:mocktail/mocktail.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:universal_io/io.dart';

import '../../../utils/mocks.dart';

extension on String {
String get fixturePath => path.join(
'test/src/commands/check/fixtures/',
this,
);
}

void main() {
group(
'''
Expand Down Expand Up @@ -79,10 +72,24 @@ THEN the trace file coverage should be checked and approved
''',
() async {
// ARRANGE
final traceFilePath = 'lcov.info'.fixturePath;
final traceFileFile = File(traceFilePath);
final directory = Directory.systemTemp.createTempSync();
final traceFileContent = '''
SF:${path.join('path', 'to', 'source_file.dart')}
DA:1,1
DA:2,0
DA:3,1
DA:4,1
DA:5,0
LF:5
LH:3
end_of_record
''';
final traceFilePath = path.join(directory.path, 'lcov.info');
final traceFileFile = File(traceFilePath)
..createSync()
..writeAsStringSync(traceFileContent);
final traceFile = TraceFile.parse(traceFileFile.readAsStringSync());
const minCoverage = 50;
const minCoverage = 50.0;

expect(traceFileFile.existsSync(), isTrue);
expect(traceFile.coverage, greaterThan(minCoverage));
Expand All @@ -108,6 +115,7 @@ THEN the trace file coverage should be checked and approved
verification.called(1);
}
verify(() => out.writeln());
directory.deleteSync(recursive: true);
},
);

Expand All @@ -125,10 +133,24 @@ THEN the trace file coverage should be checked and disapproved
''',
() async {
// ARRANGE
final traceFilePath = 'lcov.info'.fixturePath;
final traceFileFile = File(traceFilePath);
final directory = Directory.systemTemp.createTempSync();
final traceFileContent = '''
SF:${path.join('path', 'to', 'source_file.dart')}
DA:1,1
DA:2,0
DA:3,1
DA:4,1
DA:5,0
LF:5
LH:3
end_of_record
''';
final traceFilePath = path.join(directory.path, 'lcov.info');
final traceFileFile = File(traceFilePath)
..createSync()
..writeAsStringSync(traceFileContent);
final traceFile = TraceFile.parse(traceFileFile.readAsStringSync());
const minCoverage = 90;
const minCoverage = 75.0;

expect(traceFileFile.existsSync(), isTrue);
expect(traceFile.coverage, lessThan(minCoverage));
Expand Down Expand Up @@ -157,10 +179,10 @@ THEN an error indicating the issue should be thrown
''',
() async {
// ARRANGE
final absentFilePath = 'absent.lcov.info'.fixturePath;
final directory = Directory.systemTemp.createTempSync();
final absentFilePath = path.join(directory.path, 'absent.lcov.info');
final absentFile = File(absentFilePath);
const minCoverage = 50;

expect(absentFile.existsSync(), isFalse);

// ACT
Expand All @@ -173,6 +195,7 @@ THEN an error indicating the issue should be thrown

// ASSERT
expect(action, throwsA(isA<UsageException>()));
directory.deleteSync(recursive: true);
},
);

Expand Down
25 changes: 0 additions & 25 deletions packages/coverde_cli/test/src/commands/check/fixtures/lcov.info

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import 'package:coverde/src/commands/check/min_coverage.exception.dart';
import 'package:coverde/src/entities/trace_file.dart';
import 'package:coverde/src/utils/path.dart';
import 'package:io/io.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:universal_io/io.dart';

extension on String {
String get fixturePath => path.join(
'test/src/commands/check/fixtures/',
this,
);
}

void main() {
group(
Expand All @@ -21,10 +13,19 @@ GIVEN a minimum coverage exception
├─ AND holds a trace file''',
() {
// ARRANGE
const minCoverage = 40.0;
final traceFilePath = 'lcov.info'.fixturePath;
final traceFileFile = File(traceFilePath);
final traceFile = TraceFile.parse(traceFileFile.readAsStringSync());
const minCoverage = 90.0;
final traceFileContent = '''
SF:${path.join('path', 'to', 'source_file.dart')}
DA:1,1
DA:2,1
DA:3,1
DA:4,1
DA:5,0
LF:5
LH:4
end_of_record
''';
final traceFile = TraceFile.parse(traceFileContent);
final exception = MinCoverageException(
minCoverage: minCoverage,
traceFile: traceFile,
Expand Down
Loading

0 comments on commit 0a54537

Please sign in to comment.