' for "test 1"'; } expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.name).to.equal(failureMessage); expect(reporter._testsuites[1].testsuite[1].testcase[1].failure._attr.message).to.equal('error in before'); expect(reporter._testsuites[2].testsuite[0]._attr.name).to.equal('good suite'); expect(reporter._testsuites[2].testsuite[1].testcase).to.have.lengthOf(1); expect(reporter._testsuites[2].testsuite[1].testcase[0]._attr.name).to.equal('good suite test 2'); done(); }); }); it('properly diffs errors from Chai', function(done) { var reporter = createReporter(); var rootSuite = reporter.runner.suite; var suite1 = Suite.create(rootSuite, 'failing with Chai'); suite1.addTest(createTest('test 1', function () { expect({}).to.deep.equal({missingProperty: true}); })); runRunner(reporter.runner, function() { if (reporter.runner.dispose) { reporter.runner.dispose(); } expect(reporter._testsuites).to.have.lengthOf(2); expect(reporter._testsuites[1].testsuite[0]._attr.name).to.equal('failing with Chai'); expect(reporter._testsuites[1].testsuite[1].testcase).to.have.lengthOf(2); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.name).to.equal('failing with Chai test 1'); expect(reporter._testsuites[1].testsuite[1].testcase[1].failure._attr.message).to.equal('expected {} to deeply equal { missingProperty: true }'); expect(reporter._testsuites[1].testsuite[1].testcase[1].failure._cdata).to.match(/AssertionError: expected {} to deeply equal {\s*missingProperty:\s*true\s*}\n(?:\s* at .*?\n)*\n\s*\+ expected - actual\n+\s*-{}\n\s*\+{\n\s*\+\s*"missingProperty":\s*true\n\s*\+}[\s\S]*/); done(); }); }); describe('when "useFullSuiteTitle" option is specified', function() { it('generates full suite title', function(done) { var reporter = createReporter({useFullSuiteTitle: true }); runTests(reporter, function() { expect(suiteName(reporter._testsuites[0])).to.equal(''); expect(suiteName(reporter._testsuites[1])).to.equal('Root Suite Foo Bar'); expect(suiteName(reporter._testsuites[2])).to.equal('Root Suite Another suite!'); done(); }); }); it('generates full suite title separated by "suiteTitleSeparatedBy" option', function(done) { var reporter = createReporter({useFullSuiteTitle: true, suiteTitleSeparatedBy: '.'}); runTests(reporter, function() { expect(suiteName(reporter._testsuites[0])).to.equal(''); expect(suiteName(reporter._testsuites[1])).to.equal('Root Suite.Foo Bar'); expect(suiteName(reporter._testsuites[2])).to.equal('Root Suite.Another suite!'); done(); }); }); function suiteName(suite) { return suite.testsuite[0]._attr.name; } }); describe('when "outputs" option is specified', function() { it('adds output/error lines to xml report', function(done) { var reporter = createReporter({outputs: true}); var test = createTest('has outputs'); test.consoleOutputs = [ 'hello', 'world' ]; test.consoleErrors = [ 'typical diagnostic info', 'all is OK' ]; var suite = Suite.create(reporter.runner.suite, 'with console output and error'); suite.addTest(test); runRunner(reporter.runner, function() { expect(reporter._testsuites[1].testsuite[0]._attr.name).to.equal(suite.title); expect(reporter._testsuites[1].testsuite[1].testcase).to.have.length(3); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.name).to.equal(test.fullTitle()); expect(reporter._testsuites[1].testsuite[1].testcase[1]).to.have.property('system-out', 'hello\nworld'); expect(reporter._testsuites[1].testsuite[1].testcase[2]).to.have.property('system-err', 'typical diagnostic info\nall is OK'); expect(reporter._xml).to.include('hello\nworld'); expect(reporter._xml).to.include('typical diagnostic info\nall is OK'); done(); }); }); it('does not add system-out if no outputs/errors were passed', function(done) { var reporter = createReporter({outputs: true}); var test = createTest('has outputs'); var suite = Suite.create(reporter.runner.suite, 'with console output and error'); suite.addTest(test); runRunner(reporter.runner, function() { expect(reporter._testsuites[1].testsuite[0]._attr.name).to.equal(suite.title); expect(reporter._testsuites[1].testsuite[1].testcase).to.have.length(1); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.name).to.equal(test.fullTitle()); expect(reporter._xml).not.to.include(''); expect(reporter._xml).not.to.include(''); done(); }); }); it('does not add system-out if outputs/errors were empty', function(done) { var reporter = createReporter({outputs: true}); var test = createTest('has outputs'); test.consoleOutputs = []; test.consoleErrors = []; var suite = Suite.create(reporter.runner.suite, 'with console output and error'); suite.addTest(test); runRunner(reporter.runner, function() { expect(reporter._testsuites[1].testsuite[0]._attr.name).to.equal(suite.title); expect(reporter._testsuites[1].testsuite[1].testcase).to.have.length(1); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.name).to.equal(test.fullTitle()); expect(reporter._xml).not.to.include(''); expect(reporter._xml).not.to.include(''); done(); }); }); }); describe('when "attachments" option is specified', function() { it('adds attachments to xml report', function(done) { var filePath = '/path/to/file'; var reporter = createReporter({attachments: true}); var test = createTest('has attachment'); test.attachments = [filePath]; var suite = Suite.create(reporter.runner.suite, 'with attachments'); suite.addTest(test); runRunner(reporter.runner, function() { expect(reporter._testsuites[1].testsuite[0]._attr.name).to.equal(suite.title); expect(reporter._testsuites[1].testsuite[1].testcase).to.have.length(2); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.name).to.equal(test.fullTitle()); expect(reporter._testsuites[1].testsuite[1].testcase[1]).to.have.property('system-out', '[[ATTACHMENT|' + filePath + ']]'); expect(reporter._xml).to.include('[[ATTACHMENT|' + filePath + ']]'); done(); }); }); it('does not add system-out if no attachments were passed', function(done) { var reporter = createReporter({attachments: true}); var test = createTest('has attachment'); var suite = Suite.create(reporter.runner.suite, 'with attachments'); suite.addTest(test); runRunner(reporter.runner, function() { expect(reporter._testsuites[1].testsuite[0]._attr.name).to.equal(suite.title); expect(reporter._testsuites[1].testsuite[1].testcase).to.have.lengthOf(1); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.name).to.equal(test.fullTitle()); expect(reporter._xml).to.not.include(''); done(); }); }); it('does not add system-out if attachments array is empty', function(done) { var reporter = createReporter({attachments: true}); var test = createTest('has attachment'); test.attachments = []; var suite = Suite.create(reporter.runner.suite, 'with attachments'); suite.addTest(test); runRunner(reporter.runner, function() { expect(reporter._testsuites[1].testsuite[0]._attr.name).to.equal(suite.title); expect(reporter._testsuites[1].testsuite[1].testcase).to.have.lengthOf(1); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.name).to.equal(test.fullTitle()); expect(reporter._xml).to.not.include(''); done(); }); }); it('includes both console outputs and attachments in XML', function(done) { var reporter = createReporter({attachments: true, outputs: true}); var test = createTest('has attachment'); var filePath = '/path/to/file'; test.attachments = [filePath]; test.consoleOutputs = [ 'first console line', 'second console line' ]; var suite = Suite.create(reporter.runner.suite, 'with attachments and outputs'); suite.addTest(test); runRunner(reporter.runner, function() { expect(reporter._testsuites[1].testsuite[0]._attr.name).to.equal(suite.title); expect(reporter._testsuites[1].testsuite[1].testcase).to.have.length(2); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.name).to.equal(test.fullTitle()); expect(reporter._testsuites[1].testsuite[1].testcase[1]).to.have.property('system-out', 'first console line\nsecond console line\n[[ATTACHMENT|' + filePath + ']]'); expect(reporter._xml).to.include('first console line\nsecond console line\n[[ATTACHMENT|' + filePath + ']]'); done(); }); }); }); describe('Output', function() { it('skips suites with empty title', function(done) { var reporter = createReporter(); var suite = Suite.create(reporter.runner.suite, ''); suite.root = false; // mocha treats suites with empty title as root, so not sure this is possible suite.addTest(createTest('test')); runRunner(reporter.runner, function() { expect(reporter._testsuites).to.have.lengthOf(1); expect(reporter._testsuites[0].testsuite[0]._attr.name).to.equal('Root Suite'); done(); }); }); it('skips suites without testcases and suites', function(done) { var reporter = createReporter(); Suite.create(reporter.runner.suite, 'empty suite'); // mocha won't emit the `suite` event if a suite has no tests in it, so we won't even output the root suite. // See https://github.com/mochajs/mocha/blob/c0137eb698add08f29035467ea1dc230904f82ba/lib/runner.js#L723. runRunner(reporter.runner, function() { expect(reporter._testsuites).to.have.lengthOf(0); done(); }); }); it('skips suites without testcases even if they have nested suites', function(done) { var reporter = createReporter(); var suite1 = Suite.create(reporter.runner.suite, 'suite'); Suite.create(suite1, 'nested suite'); runRunner(reporter.runner, function() { // even though we have nested suites, there are no tests so mocha won't emit the `suite` event expect(reporter._testsuites).to.have.lengthOf(0); done(); }); }); it('does not skip suites with nested tests', function(done) { var reporter = createReporter(); var suite = Suite.create(reporter.runner.suite, 'nested suite'); suite.addTest(createTest('test')); runRunner(reporter.runner, function() { expect(reporter._testsuites).to.have.lengthOf(2); expect(reporter._testsuites[0].testsuite[0]._attr.name).to.equal('Root Suite'); expect(reporter._testsuites[1].testsuite[1].testcase).to.have.lengthOf(1); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.name).to.equal('nested suite test'); done(); }); }); it('does not skip root suite', function(done) { var reporter = createReporter(); reporter.runner.suite.addTest(createTest('test')); runRunner(reporter.runner, function() { expect(reporter._testsuites).to.have.lengthOf(1); expect(reporter._testsuites[0].testsuite[0]._attr.name).to.equal('Root Suite'); expect(reporter._testsuites[0].testsuite[1].testcase).to.have.lengthOf(1); var expectedName = 'test'; if (['2', '3'].includes(mochaVersion)) { expectedName = ' ' + expectedName; } expect(reporter._testsuites[0].testsuite[1].testcase[0]._attr.name).to.equal(expectedName); done(); }); }); it('respects the `rootSuiteTitle`', function(done) { var name = 'The Root Suite!'; var reporter = createReporter({rootSuiteTitle: name}); reporter.runner.suite.addTest(createTest('test')); runRunner(reporter.runner, function() { expect(reporter._testsuites).to.have.lengthOf(1); expect(reporter._testsuites[0].testsuite[0]._attr.name).to.equal(name); done(); }); }); it('uses "Mocha Tests" by default', function(done) { var reporter = createReporter(); reporter.runner.suite.addTest(createTest('test')); runRunner(reporter.runner, function() { expect(reporter._xml).to.include('testsuites name="Mocha Tests"'); done(); }); }); it('respects the `testsuitesTitle`', function(done) { var title = 'SuitesTitle'; var reporter = createReporter({testsuitesTitle: title}); reporter.runner.suite.addTest(createTest('test')); runRunner(reporter.runner, function() { expect(reporter._xml).to.include('testsuites name="SuitesTitle"'); done(); }); }); }); describe('Feature "Configurable classname/name switch"', function() { var mockedTestCase = { title: "should behave like so", timestamp: 123, tests: "1", failures: "0", time: "0.004", fullTitle: function() { return 'Super Suite ' + this.title; } }; it('should generate valid testCase for testCaseSwitchClassnameAndName default', function() { var reporter = createReporter(); var testCase = reporter.getTestcaseData(mockedTestCase); expect(testCase.testcase[0]._attr.name).to.equal(mockedTestCase.fullTitle()); expect(testCase.testcase[0]._attr.classname).to.equal(mockedTestCase.title); }); it('should generate valid testCase for testCaseSwitchClassnameAndName=false', function() { var reporter = createReporter({testCaseSwitchClassnameAndName: false}); var testCase = reporter.getTestcaseData(mockedTestCase); expect(testCase.testcase[0]._attr.name).to.equal(mockedTestCase.fullTitle()); expect(testCase.testcase[0]._attr.classname).to.equal(mockedTestCase.title); }); it('should generate valid testCase for testCaseSwitchClassnameAndName=true', function() { var reporter = createReporter({testCaseSwitchClassnameAndName: true}); var testCase = reporter.getTestcaseData(mockedTestCase); expect(testCase.testcase[0]._attr.name).to.equal(mockedTestCase.title); expect(testCase.testcase[0]._attr.classname).to.equal(mockedTestCase.fullTitle()); }); }); describe('XML format', function () { it('generates Jenkins compatible XML when in jenkinsMode', function(done) { this.timeout(10000); // xmllint is very slow var reporter = createReporter({jenkinsMode: true}); var rootSuite = reporter.runner.suite; var suite1 = Suite.create(rootSuite, 'Inner Suite'); suite1.addTest(createTest('test')); var suite2 = Suite.create(rootSuite, 'Another Suite'); suite2.addTest(createTest('test', function(done) { done(new Error('failed test')); })); runRunner(reporter.runner, function() { var schema = fs.readFileSync(path.join(__dirname, 'resources', 'jenkins-junit.xsd')); var result = xmllint.validateXML({ xml: reporter._xml, schema: schema }); expect(result.errors).to.equal(null, JSON.stringify(result.errors)); done(); }); }); it('generates Ant compatible XML when in antMode', function(done) { this.timeout(10000); // xmllint is very slow var reporter = createReporter({antMode: true}); var rootSuite = reporter.runner.suite; var suite1 = Suite.create(rootSuite, 'Inner Suite'); suite1.addTest(createTest('test')); var suite2 = Suite.create(rootSuite, 'Another Suite'); suite2.addTest(createTest('test', function(done) { done(new Error('failed test')); })); runRunner(reporter.runner, function() { var schema = fs.readFileSync(path.join(__dirname, 'resources', 'JUnit.xsd')); var result = xmllint.validateXML({ xml: reporter._xml, schema: schema }); expect(result.errors).to.equal(null, JSON.stringify(result.errors)); done(); }); }); describe('Jenkins format', function () { it('generates Jenkins compatible classnames and suite name', function(done) { var reporter = createReporter({jenkinsMode: true}); var rootSuite = reporter.runner.suite; var suite1 = Suite.create(rootSuite, 'Inner Suite'); suite1.addTest(createTest('test')); var suite2 = Suite.create(suite1, 'Another Suite'); suite2.addTest(createTest('fail test', function(done) { done(new Error('failed test')); })); runRunner(reporter.runner, function() { expect(reporter._testsuites[0].testsuite[0]._attr.name).to.equal(''); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.name).to.equal('test'); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.classname).to.equal('Inner Suite'); expect(reporter._testsuites[2].testsuite[0]._attr.name).to.equal('Root Suite.Inner Suite.Another Suite'); expect(reporter._testsuites[2].testsuite[1].testcase[0]._attr.name).to.equal('fail test'); expect(reporter._testsuites[2].testsuite[1].testcase[0]._attr.classname).to.equal('Inner Suite.Another Suite'); done(); }); }); it('prefix is added to a classname when jenkinsClassnamePrefix is specified', function(done) { var reporter = createReporter({jenkinsMode: true, jenkinsClassnamePrefix: "Added Prefix"}); var rootSuite = reporter.runner.suite; var suite1 = Suite.create(rootSuite, 'Inner Suite'); suite1.addTest(createTest('test')); var suite2 = Suite.create(suite1, 'Another Suite'); suite2.addTest(createTest('fail test', function(done) { done(new Error('failed test')); })); runRunner(reporter.runner, function() { expect(reporter._testsuites[0].testsuite[0]._attr.name).to.equal(''); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.name).to.equal('test'); expect(reporter._testsuites[1].testsuite[1].testcase[0]._attr.classname).to.equal('Added Prefix.Inner Suite'); expect(reporter._testsuites[2].testsuite[0]._attr.name).to.equal('Root Suite.Inner Suite.Another Suite'); expect(reporter._testsuites[2].testsuite[1].testcase[0]._attr.name).to.equal('fail test'); expect(reporter._testsuites[2].testsuite[1].testcase[0]._attr.classname).to.equal('Added Prefix.Inner Suite.Another Suite'); done(); }); }); }); }); });