{"id":13410,"library":"junit-merge","title":"NodeJS JUnit XML Merger","description":"junit-merge is a Node.js command-line interface (CLI) tool designed for consolidating multiple JUnit XML test reports into a single, unified XML file. This is particularly useful in CI/CD environments where parallel test runners generate numerous individual report files that need to be aggregated for a comprehensive overview or integration with other reporting systems. The current stable version is 2.0.0. While the package doesn't specify a formal release cadence, updates are typically driven by Node.js compatibility changes or new feature requirements. Its primary differentiator is its simplicity and focus as a dedicated CLI for this specific task within the Node.js ecosystem, allowing for easy integration into build scripts without requiring complex programmatic setups. It supports features like merging all results in a directory, recursive directory merging, and specifying an output file.","status":"active","version":"2.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/drazisil/junit-merge","tags":["javascript","junit"],"install":[{"cmd":"npm install junit-merge","lang":"bash","label":"npm"},{"cmd":"yarn add junit-merge","lang":"bash","label":"yarn"},{"cmd":"pnpm add junit-merge","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"While primarily a CLI tool, this assumes a default export of the main CLI execution function for programmatic use, although direct programmatic API is not explicitly documented. The common usage is via the command line.","wrong":"const junitMerge = require('junit-merge');","symbol":"junitMerge","correct":"import junitMerge from 'junit-merge';"},{"note":"This import is speculative, assuming the core file merging logic might be exposed as a named export for programmatic integration. Developers should prioritize CLI usage unless an explicit API is found in the source.","wrong":"const { mergeFiles } = require('junit-merge');","symbol":"mergeFiles","correct":"import { mergeFiles } from 'junit-merge';"},{"note":"This assumes a named export for the CLI's entry point function, potentially allowing a script to programmatically invoke the CLI logic by passing arguments. This is not explicitly documented API.","wrong":"const cli = require('junit-merge').cli;","symbol":"cli","correct":"import { cli } from 'junit-merge';"}],"quickstart":{"code":"import { execSync } from 'node:child_process';\nimport { writeFileSync, mkdirSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\n\nconst tempDir = join(process.cwd(), 'temp_junit_reports');\nconst outputFile = join(process.cwd(), 'merged-results.xml');\n\n// Clean up previous runs\nrmSync(tempDir, { recursive: true, force: true });\nrmSync(outputFile, { force: true });\nmkdirSync(tempDir, { recursive: true });\n\n// Simulate creating dummy JUnit XML files\nwriteFileSync(join(tempDir, 'report1.xml'), `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<testsuites name=\"Suite1\" tests=\"2\" failures=\"0\" errors=\"0\" time=\"1.0\">\\n  <testsuite name=\"TestA\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"0.5\">\\n    <testcase name=\"testMethod1\" classname=\"package.ClassA\" time=\"0.2\"/>\\n  </testsuite>\\n  <testsuite name=\"TestB\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"0.5\">\\n    <testcase name=\"testMethod2\" classname=\"package.ClassB\" time=\"0.3\"/>\\n  </testsuite>\\n</testsuites>`);\n\nwriteFileSync(join(tempDir, 'report2.xml'), `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<testsuites name=\"Suite2\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"0.8\">\\n  <testsuite name=\"TestC\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"0.8\">\\n    <testcase name=\"testMethod3\" classname=\"package.ClassC\" time=\"0.8\"/>\\n  </testsuite>\\n</testsuites>`);\n\nconsole.log('Dummy JUnit reports created in:', tempDir);\n\ntry {\n  // Run junit-merge CLI command\n  const command = `junit-merge -d ${tempDir} -o ${outputFile}`;\n  console.log(`Executing: ${command}`);\n  const output = execSync(command, { encoding: 'utf8' });\n  console.log('CLI Output:', output);\n  console.log('Merged report saved to:', outputFile);\n} catch (error) {\n  console.error('Error merging reports:', error.message);\n  process.exit(1);\n}\n\n// Clean up generated files (optional)\n// rmSync(tempDir, { recursive: true, force: true });\n// rmSync(outputFile, { force: true });\n","lang":"typescript","description":"This quickstart demonstrates how to use the `junit-merge` CLI to combine multiple JUnit XML reports from a directory into a single output file using Node.js's `child_process` module. It includes setup for dummy reports and cleanup."},"warnings":[{"fix":"Upgrade your Node.js runtime to version 6, 8, 10, or a more recent compatible LTS version (e.g., `nvm install 16` or `nvm use 16`).","message":"Version 2.0.0 of `junit-merge` dropped support for Node.js v4. Users on older Node.js environments must upgrade their Node.js version to v6, v8, or v10 (or newer compatible versions) to use `junit-merge` v2.0.0 and beyond.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Prefer using `junit-merge` via `child_process.execSync` or `spawn` within Node.js scripts for reliable integration, mirroring its CLI usage, rather than attempting direct module imports.","message":"The package is primarily a CLI tool; direct programmatic API usage (via `import` or `require`) is not explicitly documented. While internal components might be importable, the intended and most stable interaction is through the command line.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Validate the integrity and format of source XML files before running `junit-merge`. Consider adding a pre-processing step to check XML validity if file sources are untrusted.","message":"When merging files from a directory (`-d` option), ensure that the specified directory contains valid JUnit XML files. Malformed XML or non-XML files might lead to parsing errors and unexpected behavior in the output.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Install the package globally using `npm install -g junit-merge` or ensure your PATH includes the directory where npm installs global packages.","cause":"`junit-merge` was not installed globally or is not in the system's PATH.","error":"command not found: junit-merge"},{"fix":"Ensure the input directory specified by `-d` exists before running the command, or use the `-C` (create directory) option if you expect the output directory to be created, though this option is for the *output* directory, not input.","cause":"The directory specified with the `-d` option does not exist.","error":"Error: ENOENT: no such file or directory, scandir './non-existent-dir'"},{"fix":"Inspect the specified XML file (`path/to/malformed.xml`) for syntax errors, missing tags, or incorrect encoding. Ensure all input files adhere to the JUnit XML schema.","cause":"One of the input XML files is not valid JUnit XML or is corrupted, causing the parser to fail.","error":"Error: Unable to parse XML file: 'path/to/malformed.xml'"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":"","cli_version":null}