{"id":15376,"library":"rosie","title":"Rosie Factory for Test Data","description":"Rosie is a JavaScript library designed to create factories for building complex JavaScript objects, primarily for setting up test data. Inspired by Ruby's `factory_bot` (formerly `factory_girl`), it simplifies the generation of structured data. The current stable version is 2.1.1. Key features include defining factories with attributes, sequences for unique values, options to programmatically generate attributes without including them in the final object, and callbacks for post-build processing. Factories can also inherit from others, promoting reusability. Rosie differentiates itself by offering a flexible, declarative way to construct objects, managing inter-attribute dependencies and providing fine-grained control over the generated data structure, making it highly suitable for unit and integration testing where consistent, yet varied, data is required. There is no explicit release cadence, but the project maintains a stable API.","status":"active","version":"2.1.1","language":"javascript","source_language":"en","source_url":"git://github.com/rosiejs/rosie","tags":["javascript","factory","rosie","test"],"install":[{"cmd":"npm install rosie","lang":"bash","label":"npm"},{"cmd":"yarn add rosie","lang":"bash","label":"yarn"},{"cmd":"pnpm add rosie","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Rosie exports `Factory` as a named export. While the package specifies Node.js >=10, native ESM support for `import` without transpilation is generally stable in Node.js >=12. For older Node.js versions, a transpiler like Babel may be required.","wrong":"import Factory from 'rosie'; // Rosie exports a named 'Factory', not a default.","symbol":"Factory","correct":"import { Factory } from 'rosie'; // For ESM environments"},{"note":"The `Factory` object is directly accessible as a named property from the CommonJS `require` result. This is the recommended way to import in CommonJS.","wrong":"const Factory = require('rosie'); // This would import the entire module object, not the Factory instance directly.","symbol":"Factory","correct":"const { Factory } = require('rosie'); // For CommonJS environments"},{"note":"Type definitions are available via `@types/rosie`. Ensure `@types/rosie` is installed for correct type inference and autocompletion in TypeScript projects.","wrong":"import Factory from 'rosie'; // Incorrect default import for TypeScript","symbol":"Factory","correct":"/// <reference types=\"rosie\" />\nimport { Factory } from 'rosie'; // For TypeScript"}],"quickstart":{"code":"import { Factory } from 'rosie';\n\n// Define a 'game' factory with sequences, attributes, and dependent attributes.\nFactory.define('game')\n  .sequence('id')\n  .attr('is_over', false)\n  .attr('created_at', () => new Date())\n  .attr('random_seed', () => Math.random())\n  .attr('players', ['players'], (players) => {\n    if (!players) {\n      players = [{}, {}];\n    }\n    return players.map((data) => Factory.attributes('player', data));\n  });\n\n// Define a 'player' factory, extended by 'disabled-player'.\nFactory.define('player')\n  .sequence('id')\n  .sequence('name', (i) => `player${i}`)\n  .attr('position', ['id'], (id) => {\n    const positions = ['pitcher', '1st base', '2nd base', '3rd base'];\n    return positions[id % positions.length];\n  });\n\n// Extend the 'player' factory to create a 'disabled-player'.\nFactory.define('disabled-player').extend('player').attr('state', 'disabled');\n\n// Build an object, overriding some attributes.\nconst game = Factory.build('game', { is_over: true });\nconsole.log('Built Game:', game);\n\n// Build an object using the extended factory.\nconst disabledPlayer = Factory.build('disabled-player');\nconsole.log('Built Disabled Player:', disabledPlayer);\n\n// Get just the attributes without invoking a constructor.\nconst gameAttributes = Factory.attributes('game', { is_over: false });\nconsole.log('Game Attributes:', gameAttributes);\n\n// Example with options (options are not part of the final object).\nFactory.define('matches')\n  .attr('seasonStart', '2024-01-01')\n  .option('numMatches', 2)\n  .attr('matches', ['numMatches', 'seasonStart'], (numMatches, seasonStart) => {\n    const matches = [];\n    for (let i = 1; i <= numMatches; i++) {\n      const matchDate = new Date(seasonStart);\n      matchDate.setDate(matchDate.getDate() + (i * 7)); // Add weeks\n      matches.push({\n        matchDate: matchDate.toISOString().split('T')[0],\n        homeScore: Math.floor(Math.random() * 5),\n        awayScore: Math.floor(Math.random() * 5)\n      });\n    }\n    return matches;\n  });\n\nconst matchData = Factory.build('matches', { seasonStart: '2024-03-12' }, { numMatches: 3 });\nconsole.log('Match Data with options:', matchData);\n","lang":"typescript","description":"This quickstart demonstrates defining multiple factories, including inheritance, using sequences, dependent attributes, overriding attributes during build, and utilizing options that influence object creation without being part of the final output. It covers the core `define`, `build`, and `attributes` methods."},"warnings":[{"fix":"For older Node.js environments, use CommonJS `require` syntax (`const { Factory } = require('rosie');`) or integrate a transpiler like Babel into your build process to handle ESM imports.","message":"When using ESM `import` syntax in Node.js environments older than Node.js 12, a transpilation step (e.g., with Babel) might be necessary. While `engines.node >=10` is specified, native ESM support became stable later. Without transpilation, direct ESM imports might fail on Node.js 10/11.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Review the usage documentation for `.attr()` vs `.option()` carefully. Use `.attr()` for data that should appear in the final object, and `.option()` for configuration parameters that control how the object is built but are not part of its schema.","message":"Distinguish carefully between `attr` and `option`. Attributes (`attr`) define properties that will be present in the final built object. Options (`option`) are parameters used *during* the object generation process but are *not* included in the resulting object. Misunderstanding this can lead to unexpected keys in your test data or missing data needed for generation.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For isolated factory definitions, create factory instances directly: `const myFactory = new Factory().define('myModel');`. For global singleton cleanup between tests, ensure `Factory.reset()` is called in a `beforeEach` or `afterEach` hook in your test runner.","message":"Rosie's default behavior involves a global `Factory` singleton. If you are running tests in parallel or in environments where global state can cause interference, definitions might conflict. To avoid this, consider using 'unregistered factories' or explicitly calling `Factory.reset()`.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Ensure you are importing `Factory` correctly: `const { Factory } = require('rosie');`.","cause":"The `Factory` object was not correctly imported or made available in the current scope for CommonJS modules.","error":"ReferenceError: Factory is not defined"},{"fix":"Verify the CommonJS import: `const { Factory } = require('rosie');`. If you used `const Factory = require('rosie');`, it will likely yield this error because the module's default export isn't the `Factory` itself, but an object containing `Factory` as a property.","cause":"This usually means `Factory` was imported incorrectly in a CommonJS module, resulting in `undefined` or an unexpected object instead of the actual `Factory` instance with its methods.","error":"TypeError: Cannot read properties of undefined (reading 'define')"},{"fix":"Correct the ESM import statement to use named import syntax: `import { Factory } from 'rosie';`.","cause":"This error occurs in an ESM context when attempting to import `Factory` as a default export (`import Factory from 'rosie';`) while it is a named export.","error":"TypeError: The requested module 'rosie' does not provide an export named 'Factory'"},{"fix":"Ensure `Factory.define('myFactoryName', ...)` has been called before attempting to `Factory.build('myFactoryName', ...)` or `Factory.attributes('myFactoryName', ...)`. If using `Factory.reset()`, ensure definitions are re-run before tests.","cause":"You are trying to build an object from a factory that has not been defined or has been reset.","error":"Error: Factory named 'myFactoryName' not found"}],"ecosystem":"npm"}