UNPKG

js-tests-results-collector

Version:

Universal test results collector for Jest, Jasmine, Mocha, Cypress, and Playwright that sends results to Buddy Works API

118 lines (100 loc) 4.2 kB
const sessionManager = require('../../core/session-manager'); const TestResultMapper = require('../../utils/test-result-mapper'); const Logger = require('../../utils/logger'); class MochaReporter { constructor(runner, options) { this.runner = runner; this.options = options; this.logger = new Logger('MochaReporter'); this.pendingSubmissions = new Set(); // Hook into Mocha's specific test result events for more accurate state capture this.runner.on('start', this.onStart.bind(this)); this.runner.on('pass', this.onTestPass.bind(this)); this.runner.on('fail', this.onTestFail.bind(this)); this.runner.on('pending', this.onTestPending.bind(this)); this.runner.on('end', this.onEnd.bind(this)); } onStart() { this.logger.debug('Mocha test run started'); } async onTestPass(test) { const submissionPromise = this.submitTestWithTracking(test, () => { // Explicitly set state to ensure correct mapping test.state = 'passed'; return TestResultMapper.mapMochaResult(test); }); // Don't await here - let it run async but track it submissionPromise.catch(error => { this.logger.error('Error processing Mocha test pass result', error); }); } async onTestFail(test, err) { const submissionPromise = this.submitTestWithTracking(test, () => { // Explicitly set state and error to ensure correct mapping test.state = 'failed'; test.err = err; return TestResultMapper.mapMochaResult(test); }); // Don't await here - let it run async but track it submissionPromise.catch(error => { this.logger.error('Error processing Mocha test fail result', error); }); } async onTestPending(test) { const submissionPromise = this.submitTestWithTracking(test, () => { // Explicitly set state to ensure correct mapping test.state = 'pending'; test.pending = true; return TestResultMapper.mapMochaResult(test); }); // Don't await here - let it run async but track it submissionPromise.catch(error => { this.logger.error('Error processing Mocha test pending result', error); }); } async submitTestWithTracking(test, resultMapperFn) { const submissionId = Symbol(); this.pendingSubmissions.add(submissionId); try { const testResult = resultMapperFn(); await sessionManager.submitTestCase(testResult); this.logger.debug(`Successfully submitted: ${testResult.name}`); } catch (error) { this.logger.error('Error processing Mocha test result', error); // Mark this as a framework error since we failed to process test results sessionManager.markFrameworkError(); } finally { this.pendingSubmissions.delete(submissionId); } } async onEnd() { this.logger.debug('Mocha test run completed'); // Wait for all pending submissions to complete if (this.pendingSubmissions.size > 0) { this.logger.debug(`Waiting for ${this.pendingSubmissions.size} pending test submissions to complete`); // Poll until all submissions are done (with timeout) const maxWaitTime = 10000; // 10 seconds const startTime = Date.now(); while (this.pendingSubmissions.size > 0 && (Date.now() - startTime) < maxWaitTime) { await new Promise(resolve => setTimeout(resolve, 100)); // Wait 100ms } if (this.pendingSubmissions.size > 0) { this.logger.warn(`Timed out waiting for ${this.pendingSubmissions.size} test submissions`); // Mark this as a framework error since we couldn't complete all submissions sessionManager.markFrameworkError(); } else { this.logger.debug('All test submissions completed'); } } try { // Close the session when all tests are finished await sessionManager.closeSession(); this.logger.debug('Session closed after Mocha test completion'); } catch (error) { this.logger.error('Error closing session after Mocha test completion', error); // Mark this as a framework error sessionManager.markFrameworkError(); } } } module.exports = MochaReporter;