From f6d50f6ebf4806d40d83ae8d6f18c8be7d4f2cab Mon Sep 17 00:00:00 2001 From: Timmy Willison Date: Thu, 13 Feb 2025 22:25:44 -0500 Subject: [PATCH 1/3] fix(report): add global QUnit errors to reporter --- listeners.js | 4 ++++ reporter.js | 6 ++++++ run.js | 17 +++++++++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/listeners.js b/listeners.js index ef4a6bd..035a77c 100644 --- a/listeners.js +++ b/listeners.js @@ -86,6 +86,10 @@ // Send acknowledgement to the server. send( "ack" ); + QUnit.on( "error", function( error ) { + send( "error", { message: error.message, stack: error.stack } ); + } ); + QUnit.on( "testEnd", function( data ) { send( "testEnd", data ); } ); diff --git a/reporter.js b/reporter.js index ceef537..5cf23ba 100644 --- a/reporter.js +++ b/reporter.js @@ -113,6 +113,12 @@ export function reportTest( test, { fullBrowser, id } ) { } } +export function reportError( error ) { + console.error( chalk.red( `\n\nError: ${ error.message }` ) ); + console.error( chalk.gray( error.stack ) ); + return error; +} + export function reportEnd( result, { descriptiveUrl, fullBrowser, id } ) { console.log( `\n\nTests finished in ${ prettyMs( result.runtime ) } ` + diff --git a/run.js b/run.js index e754fdf..d29a46c 100644 --- a/run.js +++ b/run.js @@ -3,7 +3,7 @@ import { asyncExitHook, gracefulExit } from "exit-hook"; import { getLatestBrowser } from "./browserstack/api.js"; import { buildBrowserFromString } from "./browserstack/buildBrowserFromString.js"; import { localTunnel } from "./browserstack/local.js"; -import { reportEnd, reportTest } from "./reporter.js"; +import { reportEnd, reportError, reportTest } from "./reporter.js"; import { createTestServer } from "./createTestServer.js"; import { buildTestUrl } from "./lib/buildTestUrl.js"; import { generateHash, generateModuleId } from "./lib/generateHash.js"; @@ -106,6 +106,15 @@ export async function run( { } break; } + case "error": { + const reportId = message.id; + const report = reports[ reportId ]; + touchBrowser( report.browser ); + reportError( message.data ); + pendingErrors[ reportId ] ??= Object.create( null ); + pendingErrors[ reportId ][ message.data.message ] = message.data.stack; + break; + } case "runEnd": { const reportId = message.id; const report = reports[ reportId ]; @@ -127,6 +136,9 @@ export async function run( { return; } errorMessages.push( ...Object.values( pendingErrors[ reportId ] ) ); + if ( !errorMessages.length ) { + errorMessages.push( `Global failure in ${ report.url }` ); + } } // Run the next test @@ -351,7 +363,8 @@ export async function run( { gracefulExit( 0 ); } } else { - console.error( chalk.red( `${ errorMessages.length } tests failed.` ) ); + const len = errorMessages.length; + console.error( chalk.red( `${ len } test${ len > 1 ? "s" : "" } failed.` ) ); console.log( errorMessages.map( ( error, i ) => `\n${ i + 1 }. ${ error }` ).join( "\n" ) ); From c0f3b1032a526de2f1910cd010edd63c5017e3cd Mon Sep 17 00:00:00 2001 From: Timmy Willison Date: Fri, 14 Feb 2025 11:18:04 -0500 Subject: [PATCH 2/3] fixup! include error message (not just stack) in final report --- run.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/run.js b/run.js index d29a46c..2246e85 100644 --- a/run.js +++ b/run.js @@ -85,10 +85,10 @@ export async function run( { const reportId = message.id; const report = reports[ reportId ]; touchBrowser( report.browser ); - const errors = reportTest( message.data, report ); + const errorMessage = reportTest( message.data, report ); pendingErrors[ reportId ] ??= Object.create( null ); - if ( errors ) { - pendingErrors[ reportId ][ message.data.name ] = errors; + if ( errorMessage ) { + pendingErrors[ reportId ][ message.data.name ] = errorMessage; } else { const existing = pendingErrors[ reportId ][ message.data.name ]; @@ -112,7 +112,8 @@ export async function run( { touchBrowser( report.browser ); reportError( message.data ); pendingErrors[ reportId ] ??= Object.create( null ); - pendingErrors[ reportId ][ message.data.message ] = message.data.stack; + pendingErrors[ reportId ][ message.data.message ] = + `${ message.data.message }\n${ message.data.stack }`; break; } case "runEnd": { @@ -347,9 +348,9 @@ export async function run( { stop = true; console.error( chalk.red( - `No tests were run with URL "${ report.url }" in ${ getBrowserString( - report.browser - ) } (${ report.id })` + `No tests were run with URL "${ report.url }" in ${ + report.fullBrowser + } (${ report.id })` ) ); } From cb705dddf778b7f4dc8bee64283cb8bc23a02472 Mon Sep 17 00:00:00 2001 From: Timmy Willison Date: Sat, 15 Feb 2025 10:52:24 -0500 Subject: [PATCH 3/3] fixup! build error message with error.name; share reportError message --- listeners.js | 6 +++++- reporter.js | 11 ++++++++--- run.js | 5 ++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/listeners.js b/listeners.js index 035a77c..9603106 100644 --- a/listeners.js +++ b/listeners.js @@ -87,7 +87,11 @@ send( "ack" ); QUnit.on( "error", function( error ) { - send( "error", { message: error.message, stack: error.stack } ); + send( "error", { + message: error.message, + name: error.name, + stack: error.stack + } ); } ); QUnit.on( "testEnd", function( data ) { diff --git a/reporter.js b/reporter.js index 5cf23ba..cb01799 100644 --- a/reporter.js +++ b/reporter.js @@ -114,9 +114,14 @@ export function reportTest( test, { fullBrowser, id } ) { } export function reportError( error ) { - console.error( chalk.red( `\n\nError: ${ error.message }` ) ); - console.error( chalk.gray( error.stack ) ); - return error; + const title = `${ error.name || "Error" }: ${ error.message }`; + let message = chalk.red( title ); + + // Chromium error stacks include the title in the first line, + // but Firefox error stacks do not. + message += `\n${ chalk.gray( error.stack.replace( `${ title }\n`, "" ) ) }`; + console.error( `\n\n${ message }` ); + return message; } export function reportEnd( result, { descriptiveUrl, fullBrowser, id } ) { diff --git a/run.js b/run.js index 2246e85..0fc6f35 100644 --- a/run.js +++ b/run.js @@ -110,10 +110,9 @@ export async function run( { const reportId = message.id; const report = reports[ reportId ]; touchBrowser( report.browser ); - reportError( message.data ); + const errorMessage = reportError( message.data ); pendingErrors[ reportId ] ??= Object.create( null ); - pendingErrors[ reportId ][ message.data.message ] = - `${ message.data.message }\n${ message.data.stack }`; + pendingErrors[ reportId ][ message.data.message ] = errorMessage; break; } case "runEnd": {