{"id":12909,"library":"broccoli-test-helper","title":"Broccoli Test Helper","description":"broccoli-test-helper is a utility package designed to simplify the process of testing Broccoli plugins. It offers a set of helper functions, such as `createBuilder` and `createTempDir`, which streamline the setup and teardown of test environments for Broccoli-based projects. The package focuses on making tests for build and rebuild behavior straightforward and ensuring that output comparisons are 'diff friendly,' providing clear insights into file system changes. Currently stable at version 2.0.0, it supports modern JavaScript features like async/await for cleaner asynchronous test code and ships with TypeScript declarations, enhancing developer experience for TypeScript users. While no specific release cadence is noted, its recent major version indicates active development and maintenance. Its primary differentiator is its tailored approach to Broccoli plugin testing, providing abstractions that directly address common challenges in this domain, making it an an essential tool for Broccoli plugin authors.","status":"active","version":"2.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/broccolijs/broccoli-test-helper","tags":["javascript","typescript"],"install":[{"cmd":"npm install broccoli-test-helper","lang":"bash","label":"npm"},{"cmd":"yarn add broccoli-test-helper","lang":"bash","label":"yarn"},{"cmd":"pnpm add broccoli-test-helper","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Primary named exports for ESM and TypeScript usage. Avoid deep imports unless explicitly documented.","wrong":"import createBuilder from 'broccoli-test-helper/createBuilder';","symbol":"createBuilder, createTempDir","correct":"import { createBuilder, createTempDir } from 'broccoli-test-helper';"},{"note":"While CommonJS destructuring `const { createBuilder } = require('broccoli-test-helper');` often works, the official examples show assigning the module to a variable and then accessing properties, which might be safer across module export configurations.","wrong":"const { createBuilder } = require('broccoli-test-helper');","symbol":"helper object","correct":"const helper = require('broccoli-test-helper');\nconst createBuilder = helper.createBuilder;"},{"note":"TypeScript types are shipped with the package for all primary exports.","symbol":"Types","correct":"import type { Builder, TempDir } from 'broccoli-test-helper';"}],"quickstart":{"code":"import { createBuilder, createTempDir } from \"broccoli-test-helper\";\n\n// This is a placeholder for your actual Broccoli plugin.\n// In a real test, you would import and instantiate your plugin here.\nclass Herp2Derp {\n  private inputPath: string;\n  constructor(inputPath: string) { this.inputPath = inputPath; }\n  async build() { /* Your plugin's build logic would go here */ }\n}\n\n// Assuming QUnit is set up in your test environment.\n// For demonstration, a minimal QUnit-like structure is implied.\n\n// QUnit.module and QUnit.test are from the QUnit test framework.\n// Replace with your preferred test framework (e.g., Mocha, Jest) setup.\nconst QUnit = {\n  module: (name: string, cb: Function) => { console.log(`Module: ${name}`); cb(); },\n  test: (name: string, cb: Function) => { \n    console.log(`Test: ${name}`); \n    const assert = { deepEqual: (actual: any, expected: any) => console.assert(JSON.stringify(actual) === JSON.stringify(expected), 'Assertion Failed') };\n    cb(assert); \n  }\n};\n\nQUnit.module(\"Herp2Derp Plugin Test\", () => {\n  QUnit.test(\"should build and track changes correctly\", async assert => {\n    const input = await createTempDir();\n    try {\n      const subject = new Herp2Derp(input.path()); // Instantiate your plugin with the temp input path\n      const output = createBuilder(subject);\n      try {\n        // INITIAL BUILD\n        input.write({\n          \"a.herp\": \"A\",\n          lib: {\n            \"b.herp\": \"B\",\n            \"c.herp\": \"C\"\n          }\n        });\n        await output.build();\n\n        assert.deepEqual(output.read(), {\n          \"a.derp\": \"derp A!\", // Assuming Herp2Derp transforms .herp to .derp\n          lib: {\n            \"b.derp\": \"derp B!\",\n            \"c.derp\": \"derp C!\"\n          }\n        });\n        assert.deepEqual(output.changes(), {\n          \"a.derp\": \"create\",\n          \"lib/\": \"mkdir\",\n          \"lib/b.derp\": \"create\",\n          \"lib/c.derp\": \"create\"\n        });\n\n        // UPDATE AND REMOVE\n        input.write({\n          \"a.herp\": \"AA\", // Change a file\n          lib: null // Remove a directory\n        });\n        await output.build();\n\n        assert.deepEqual(output.read(), {\n          \"a.derp\": \"derp AA!\"\n        });\n        assert.deepEqual(output.changes(), {\n          \"lib/c.derp\": \"unlink\",\n          \"lib/b.derp\": \"unlink\",\n          \"lib/\": \"rmdir\",\n          \"a.derp\": \"change\"\n        });\n\n        // NOOP BUILD\n        await output.build();\n        assert.deepEqual(output.changes(), {}); // No changes expected\n\n      } finally {\n        await output.dispose(); // Clean up output directory\n      }\n    } finally {\n      await input.dispose(); // Clean up input directory\n    }\n  });\n});","lang":"typescript","description":"This quickstart demonstrates how to use `broccoli-test-helper` to test a Broccoli plugin, covering initial builds, updates, removals, and verifying file changes and output using `async/await` and QUnit-style assertions. The `Herp2Derp` class serves as a placeholder for your actual Broccoli plugin under test."},"warnings":[{"fix":"Ensure your Node.js environment is within the supported range. Consider using a Node.js version manager like `nvm` to switch versions.","message":"The `engines` field in `package.json` specifies Node.js versions `6.* || 8.* || >= 10.*`. Users on Node.js 9.x or versions older than 6.x may encounter compatibility issues or unexpected behavior, even if examples suggest older Node.js versions are supported with transpilation.","severity":"gotcha","affected_versions":"<6.0 || =9.x"},{"fix":"Upgrade Node.js to 7.6.0+ or configure your build pipeline to transpile `async/await` (e.g., `tsc -t ES2017` or `babel-preset-env`). For older Node.js, `co` can be used with generators.","message":"When using `async/await` syntax in your tests, ensure your Node.js environment natively supports it (Node.js 7.6.0 or higher) or that you have a build step (e.g., TypeScript compilation, Babel) configured to transpile `async/await` to an older JavaScript target compatible with your runtime environment.","severity":"gotcha","affected_versions":"<7.6.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure `require('broccoli-test-helper')` successfully returns an object. The recommended CommonJS usage shown in examples is `const helper = require('broccoli-test-helper'); const createBuilder = helper.createBuilder;`.","cause":"Attempting to access `createBuilder` from a CommonJS `require` call where `helper` might be `undefined` or the export structure is not as expected for direct property access, or trying to destructure incorrectly.","error":"TypeError: helper.createBuilder is not a function"},{"fix":"Mark your test callback function as `async`, e.g., `QUnit.test('my test', async assert => { /* ... */ });` or `it('should build', async function() { /* ... */ });`. If on older Node.js, ensure transpilation is in place.","cause":"The `await` keyword is used outside of an `async` function. This typically happens when test callbacks are not marked as `async` or when `async/await` is used in an environment without proper transpilation or native support.","error":"SyntaxError: await is only valid in async function"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":""}