mirror of
https://github.com/dorny/test-reporter.git
synced 2025-12-16 06:17:10 +01:00
Fix dart/flutter stack trace parsing
This commit is contained in:
parent
2834fd0c5f
commit
effa386fea
6 changed files with 38 additions and 25 deletions
|
|
@ -40,9 +40,9 @@ test\\\\main_test.dart 13:9 main.<fn>.<fn>.<fn>
|
||||||
"details": "package:darttest/main.dart 2:3 throwError
|
"details": "package:darttest/main.dart 2:3 throwError
|
||||||
test\\\\main_test.dart 17:9 main.<fn>.<fn>.<fn>
|
test\\\\main_test.dart 17:9 main.<fn>.<fn>.<fn>
|
||||||
",
|
",
|
||||||
"line": 2,
|
"line": 17,
|
||||||
"message": "Exception: Some error",
|
"message": "Exception: Some error",
|
||||||
"path": "lib/main.dart",
|
"path": "test/main_test.dart",
|
||||||
},
|
},
|
||||||
"name": "Test 1 Test 1.1 Exception in target unit",
|
"name": "Test 1 Test 1.1 Exception in target unit",
|
||||||
"result": "failed",
|
"result": "failed",
|
||||||
|
|
@ -159,7 +159,7 @@ When the exception was thrown, this was the stack:
|
||||||
The test description was:
|
The test description was:
|
||||||
pass updateShouldNotify
|
pass updateShouldNotify
|
||||||
════════════════════════════════════════════════════════════════════════════════════════════════════",
|
════════════════════════════════════════════════════════════════════════════════════════════════════",
|
||||||
"line": 94,
|
"line": 112,
|
||||||
"message": "Test failed. See exception logs above.
|
"message": "Test failed. See exception logs above.
|
||||||
The test description was: pass updateShouldNotify",
|
The test description was: pass updateShouldNotify",
|
||||||
"path": "test/value_listenable_provider_test.dart",
|
"path": "test/value_listenable_provider_test.dart",
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ describe('dart-json tests', () => {
|
||||||
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||||
|
|
||||||
const parser = new DartJsonParser(opts)
|
const parser = new DartJsonParser(opts, 'dart')
|
||||||
const result = await parser.parse(filePath, fileContent)
|
const result = await parser.parse(filePath, fileContent)
|
||||||
expect(result).toMatchSnapshot()
|
expect(result).toMatchSnapshot()
|
||||||
|
|
||||||
|
|
@ -42,7 +42,7 @@ describe('dart-json tests', () => {
|
||||||
workDir: '/__w/provider/provider/'
|
workDir: '/__w/provider/provider/'
|
||||||
}
|
}
|
||||||
|
|
||||||
const parser = new DartJsonParser(opts)
|
const parser = new DartJsonParser(opts, 'flutter')
|
||||||
const result = await parser.parse(filePath, fileContent)
|
const result = await parser.parse(filePath, fileContent)
|
||||||
expect(result).toMatchSnapshot()
|
expect(result).toMatchSnapshot()
|
||||||
|
|
||||||
|
|
|
||||||
28
dist/index.js
generated
vendored
28
dist/index.js
generated
vendored
|
|
@ -140,11 +140,11 @@ async function main() {
|
||||||
function getParser(reporter, options) {
|
function getParser(reporter, options) {
|
||||||
switch (reporter) {
|
switch (reporter) {
|
||||||
case 'dart-json':
|
case 'dart-json':
|
||||||
return new dart_json_parser_1.DartJsonParser(options);
|
return new dart_json_parser_1.DartJsonParser(options, 'dart');
|
||||||
case 'dotnet-trx':
|
case 'dotnet-trx':
|
||||||
return new dotnet_trx_parser_1.DotnetTrxParser(options);
|
return new dotnet_trx_parser_1.DotnetTrxParser(options);
|
||||||
case 'flutter-json':
|
case 'flutter-json':
|
||||||
return new dart_json_parser_1.DartJsonParser(options);
|
return new dart_json_parser_1.DartJsonParser(options, 'flutter');
|
||||||
case 'jest-junit':
|
case 'jest-junit':
|
||||||
return new jest_junit_parser_1.JestJunitParser(options);
|
return new jest_junit_parser_1.JestJunitParser(options);
|
||||||
default:
|
default:
|
||||||
|
|
@ -216,8 +216,9 @@ class TestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class DartJsonParser {
|
class DartJsonParser {
|
||||||
constructor(options) {
|
constructor(options, sdk) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
this.sdk = sdk;
|
||||||
}
|
}
|
||||||
async parse(path, content) {
|
async parse(path, content) {
|
||||||
const tr = this.getTestRun(path, content);
|
const tr = this.getTestRun(path, content);
|
||||||
|
|
@ -300,9 +301,12 @@ class DartJsonParser {
|
||||||
const { trackedFiles } = this.options;
|
const { trackedFiles } = this.options;
|
||||||
const message = (_b = (_a = test.error) === null || _a === void 0 ? void 0 : _a.error) !== null && _b !== void 0 ? _b : '';
|
const message = (_b = (_a = test.error) === null || _a === void 0 ? void 0 : _a.error) !== null && _b !== void 0 ? _b : '';
|
||||||
const stackTrace = (_d = (_c = test.error) === null || _c === void 0 ? void 0 : _c.stackTrace) !== null && _d !== void 0 ? _d : '';
|
const stackTrace = (_d = (_c = test.error) === null || _c === void 0 ? void 0 : _c.stackTrace) !== null && _d !== void 0 ? _d : '';
|
||||||
const print = test.print.filter(p => p.messageType === 'print').map(p => p.message).join('\n');
|
const print = test.print
|
||||||
|
.filter(p => p.messageType === 'print')
|
||||||
|
.map(p => p.message)
|
||||||
|
.join('\n');
|
||||||
const details = [print, stackTrace].filter(str => str !== '').join('\n');
|
const details = [print, stackTrace].filter(str => str !== '').join('\n');
|
||||||
const src = this.exceptionThrowSource(stackTrace, trackedFiles);
|
const src = this.exceptionThrowSource(details, trackedFiles);
|
||||||
let path;
|
let path;
|
||||||
let line;
|
let line;
|
||||||
if (src !== undefined) {
|
if (src !== undefined) {
|
||||||
|
|
@ -324,16 +328,16 @@ class DartJsonParser {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
exceptionThrowSource(ex, trackedFiles) {
|
exceptionThrowSource(ex, trackedFiles) {
|
||||||
// imports from package which is tested are listed in stack traces as 'package:xyz/' which maps to relative path 'lib/'
|
const lines = ex.split(/\r?\n/g);
|
||||||
const packageRe = /^package:[a-zA-z0-9_$]+\//;
|
|
||||||
const lines = ex.split(/\r?\n/).map(str => str.replace(packageRe, 'lib/'));
|
|
||||||
// regexp to extract file path and line number from stack trace
|
// regexp to extract file path and line number from stack trace
|
||||||
const re = /^(.*)\s+(\d+):\d+\s+/;
|
const dartRe = /^(?!package:)(.*)\s+(\d+):\d+\s+/;
|
||||||
|
const flutterRe = /^#\d+\s+.*\((?!package:)(.*):(\d+):\d+\)$/;
|
||||||
|
const re = this.sdk === 'dart' ? dartRe : flutterRe;
|
||||||
for (const str of lines) {
|
for (const str of lines) {
|
||||||
const match = str.match(re);
|
const match = str.match(re);
|
||||||
if (match !== null) {
|
if (match !== null) {
|
||||||
const [_, pathStr, lineStr] = match;
|
const [_, pathStr, lineStr] = match;
|
||||||
const path = file_utils_1.normalizeFilePath(pathStr);
|
const path = file_utils_1.normalizeFilePath(this.getRelativePath(pathStr));
|
||||||
if (trackedFiles.includes(path)) {
|
if (trackedFiles.includes(path)) {
|
||||||
const line = parseInt(lineStr);
|
const line = parseInt(lineStr);
|
||||||
return { path, line };
|
return { path, line };
|
||||||
|
|
@ -343,6 +347,10 @@ class DartJsonParser {
|
||||||
}
|
}
|
||||||
getRelativePath(path) {
|
getRelativePath(path) {
|
||||||
const { workDir } = this.options;
|
const { workDir } = this.options;
|
||||||
|
const prefix = 'file://';
|
||||||
|
if (path.startsWith(prefix)) {
|
||||||
|
path = path.substr(prefix.length);
|
||||||
|
}
|
||||||
if (path.startsWith(workDir)) {
|
if (path.startsWith(workDir)) {
|
||||||
path = path.substr(workDir.length);
|
path = path.substr(workDir.length);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
|
|
@ -131,11 +131,11 @@ async function main(): Promise<void> {
|
||||||
function getParser(reporter: string, options: ParseOptions): TestParser {
|
function getParser(reporter: string, options: ParseOptions): TestParser {
|
||||||
switch (reporter) {
|
switch (reporter) {
|
||||||
case 'dart-json':
|
case 'dart-json':
|
||||||
return new DartJsonParser(options)
|
return new DartJsonParser(options, 'dart')
|
||||||
case 'dotnet-trx':
|
case 'dotnet-trx':
|
||||||
return new DotnetTrxParser(options)
|
return new DotnetTrxParser(options)
|
||||||
case 'flutter-json':
|
case 'flutter-json':
|
||||||
return new DartJsonParser(options)
|
return new DartJsonParser(options, 'flutter')
|
||||||
case 'jest-junit':
|
case 'jest-junit':
|
||||||
return new JestJunitParser(options)
|
return new JestJunitParser(options)
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ class TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DartJsonParser implements TestParser {
|
export class DartJsonParser implements TestParser {
|
||||||
constructor(readonly options: ParseOptions) {}
|
constructor(readonly options: ParseOptions, readonly sdk: 'dart' | 'flutter') {}
|
||||||
|
|
||||||
async parse(path: string, content: string): Promise<TestRunResult> {
|
async parse(path: string, content: string): Promise<TestRunResult> {
|
||||||
const tr = this.getTestRun(path, content)
|
const tr = this.getTestRun(path, content)
|
||||||
|
|
@ -162,7 +162,7 @@ export class DartJsonParser implements TestParser {
|
||||||
.map(p => p.message)
|
.map(p => p.message)
|
||||||
.join('\n')
|
.join('\n')
|
||||||
const details = [print, stackTrace].filter(str => str !== '').join('\n')
|
const details = [print, stackTrace].filter(str => str !== '').join('\n')
|
||||||
const src = this.exceptionThrowSource(stackTrace, trackedFiles)
|
const src = this.exceptionThrowSource(details, trackedFiles)
|
||||||
let path
|
let path
|
||||||
let line
|
let line
|
||||||
|
|
||||||
|
|
@ -186,17 +186,18 @@ export class DartJsonParser implements TestParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private exceptionThrowSource(ex: string, trackedFiles: string[]): {path: string; line: number} | undefined {
|
private exceptionThrowSource(ex: string, trackedFiles: string[]): {path: string; line: number} | undefined {
|
||||||
// imports from package which is tested are listed in stack traces as 'package:xyz/' which maps to relative path 'lib/'
|
const lines = ex.split(/\r?\n/g)
|
||||||
const packageRe = /^package:[a-zA-z0-9_$]+\//
|
|
||||||
const lines = ex.split(/\r?\n/).map(str => str.replace(packageRe, 'lib/'))
|
|
||||||
|
|
||||||
// regexp to extract file path and line number from stack trace
|
// regexp to extract file path and line number from stack trace
|
||||||
const re = /^(.*)\s+(\d+):\d+\s+/
|
const dartRe = /^(?!package:)(.*)\s+(\d+):\d+\s+/
|
||||||
|
const flutterRe = /^#\d+\s+.*\((?!package:)(.*):(\d+):\d+\)$/
|
||||||
|
const re = this.sdk === 'dart' ? dartRe : flutterRe
|
||||||
|
|
||||||
for (const str of lines) {
|
for (const str of lines) {
|
||||||
const match = str.match(re)
|
const match = str.match(re)
|
||||||
if (match !== null) {
|
if (match !== null) {
|
||||||
const [_, pathStr, lineStr] = match
|
const [_, pathStr, lineStr] = match
|
||||||
const path = normalizeFilePath(pathStr)
|
const path = normalizeFilePath(this.getRelativePath(pathStr))
|
||||||
if (trackedFiles.includes(path)) {
|
if (trackedFiles.includes(path)) {
|
||||||
const line = parseInt(lineStr)
|
const line = parseInt(lineStr)
|
||||||
return {path, line}
|
return {path, line}
|
||||||
|
|
@ -207,6 +208,10 @@ export class DartJsonParser implements TestParser {
|
||||||
|
|
||||||
private getRelativePath(path: string): string {
|
private getRelativePath(path: string): string {
|
||||||
const {workDir} = this.options
|
const {workDir} = this.options
|
||||||
|
const prefix = 'file://'
|
||||||
|
if (path.startsWith(prefix)) {
|
||||||
|
path = path.substr(prefix.length)
|
||||||
|
}
|
||||||
if (path.startsWith(workDir)) {
|
if (path.startsWith(workDir)) {
|
||||||
path = path.substr(workDir.length)
|
path = path.substr(workDir.length)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue