{"id":31563458,"url":"https://github.com/legaard/mixtape","last_synced_at":"2025-10-05T04:59:29.645Z","repository":{"id":48331935,"uuid":"158124290","full_name":"legaard/mixtape","owner":"legaard","description":"📼 Fixture library for organizing and generating test data","archived":false,"fork":false,"pushed_at":"2021-08-01T04:14:40.000Z","size":1681,"stargazers_count":3,"open_issues_count":10,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-11T00:29:16.727Z","etag":null,"topics":["autofixture","builder","factory","fixture","javascript","tdd","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/legaard.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-18T20:32:43.000Z","updated_at":"2025-02-09T16:56:07.000Z","dependencies_parsed_at":"2022-09-05T06:21:12.970Z","dependency_job_id":null,"html_url":"https://github.com/legaard/mixtape","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/legaard/mixtape","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/legaard%2Fmixtape","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/legaard%2Fmixtape/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/legaard%2Fmixtape/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/legaard%2Fmixtape/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/legaard","download_url":"https://codeload.github.com/legaard/mixtape/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/legaard%2Fmixtape/sbom","scorecard":{"id":583120,"data":{"date":"2025-08-11","repo":{"name":"github.com/legaard/mixtape","commit":"94b2b2f93cd9bca51d414a08e375f4e1400fff74"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/3 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"29 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-5fw9-fq32-wv5p","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-qgmg-gppg-76g5","Warn: Project is vulnerable to: GHSA-xx4c-jj58-r7x6","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7","Warn: Project is vulnerable to: GHSA-6fc8-4gx4-v693","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T19:42:17.517Z","repository_id":48331935,"created_at":"2025-08-20T19:42:17.518Z","updated_at":"2025-08-20T19:42:17.518Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278411250,"owners_count":25982368,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["autofixture","builder","factory","fixture","javascript","tdd","typescript"],"created_at":"2025-10-05T04:59:22.964Z","updated_at":"2025-10-05T04:59:29.637Z","avatar_url":"https://github.com/legaard.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mixtape\n\n[![Build Status](https://travis-ci.org/legaard/mixtape.svg?branch=master)](https://travis-ci.org/legaard/mixtape)\n[![Coverage Status](https://coveralls.io/repos/github/legaard/mixtape/badge.svg?branch=master)](https://coveralls.io/github/legaard/mixtape?branch=master)\n[![npm](https://img.shields.io/npm/v/@mixtape/core.svg)](https://www.npmjs.com/package/@mixtape/core)\n[![npm](https://img.shields.io/npm/dm/@mixtape/core)](https://www.npmjs.com/package/@mixtape/core)\n[![David](https://img.shields.io/david/legaard/mixtape.svg)](https://david-dm.org/legaard/mixtape)\n[![David](https://img.shields.io/david/dev/legaard/mixtape.svg)](https://david-dm.org/legaard/mixtape?type=dev)\n[![license](https://img.shields.io/npm/l/@mixtape/core.svg)](https://github.com/legaard/mixtape/blob/master/LICENSE.md)\n\nA _fixture library_, written in [TypeScript](http://typescriptlang.org), for organizing and generating random test data for JavaScript/Node.js applications. Using this library should make it easy to arrange and maintain tests.\n\nThis library is heavily inspired by the C# library [AutoFixture](https://github.com/AutoFixture/AutoFixture).\n\n## Table of Contents\n\n* [Installation](#installation)\n* [Getting Started](#getting-started)\n  * [Templates and Injectors](#templates-and-injectors)\n  * [Creating Builders](#creating-builders)\n  * [Bundle Builders Using Extensions](#bundle-builders-using-extensions)\n  * [Freeze Properties](#freeze-properties)\n  * [Custom Objects](#custom-objects)\n* [Documentation](https://github.com/legaard/mixtape/wiki/Documentation)\n* [Change log](https://github.com/legaard/mixtape/blob/master/CHANGELOG.md)\n\n## Installation 💾\n\nInstall the library with `npm`\n\n```bash\nnpm install --save-dev @mixtape/core\n```\n\nor with `yarn`\n\n```bash\nyarn add --dev @mixtape/core\n```\n\n## Getting Started 🚀\n\n### Templates and Injectors\n\nThe fastest way to get started with Mixtape is to create an _injector_ (with a [`Fixture`](https://github.com/legaard/mixtape/wiki/The-Fixture-Class) constructor function), use the injector to provide the fixture in the tests and make a _template_ as a blueprint for generating test data. Here is an example:\n\n```js\nconst { Fixture, createInjector } = require('@mixtape/core');\n\nconst withFixture = createInjector(() =\u003e new Fixture());\n\ntest('test template with Mixtape', withFixture(fixture =\u003e {\n    const heroTemplate = {\n        name: 'string',\n        powers: ['string'],\n        age: 'number',\n        hasSecretIdentity: 'boolean',\n        origin: {\n            planet: 'string',\n            parents: 'undefined'\n        }\n    }\n\n    const randomHero = fixture.from(heroTemplate).create();\n\n    expect(typeof randomHero.name).toBe('string');\n    expect(randomHero.powers instanceof Array).toBeTruthy();\n    expect(typeof randomHero.age).toBe('number');\n    expect(typeof randomHero.hasSecretIdentity).toBe('boolean');\n    expect(typeof randomHero.origin).toBe('object');\n    expect(typeof randomHero.origin.planet).toBe('string');\n    expect(randomHero.origin.parents).toBeUndefined();\n}));\n```\n\n\u003e ℹ️ For injector functions: Additional arguments from the testing framework is passed after the fixture object, e.g. `withFixture((fixture, ...args) =\u003e {})`.\n\n### Creating Builders\n\nTo make things easier to maintain and to keep the tests [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself), builders can be used instead of templates. A builder can be created and added to the `extensions` property of the `Fixture` object like this:\n\n```js\nconst { Fixture, Builder } = require('@mixtape/core');\n\nclass SuperHeroBuilder extends Builder {\n    constructor() {\n        // Name of the type that the builder can create\n        super('SuperHero');\n    }\n\n    /**\n     * The `context` (a subset of Fixture methods) can be use to create other types inside the builder\n     * Using the `context` to generate data is needed for methods like ´freeze()´ to work\n     */\n    build(context) {\n        return {\n            name: context.create('string'),\n            powers: context.createMany('string', 3),\n            age: context.create('number'),\n            hasSecretIdentity: context.create('boolean')\n        }\n    }\n}\n\nconst fixture = new Fixture();\nfixture.extensions.add(new SuperHeroBuilder());\n\nconst randomHero = fixture.create('SuperHero');\n\n/**\n * Value of randomHero\n * {\n        name: 'a716b96b-3ede-4cca-8f5a-07629a3d9e2b',\n        powers: [\n            'f12183b5-08d9-4948-8259-46b6342a630d',\n            'b271e647-2eae-4629-826f-22987df5d349',\n            'e59af318-56a3-4b26-a8ff-6f0dbd1704d1'\n        ],\n        age: 117,\n        hasSecretIdentity: true\n    }\n */\n```\n\n\u003e ℹ️ Instead of using strings to denote primitive types an object (`PrimitiveType`) is also available with these types. Then creating primitive types looks likes this `fixture.create(PrimitiveType.string)`.\n\n\u003e In ES5 a similar builder looks like this:\n\u003e\n\u003e```js\n\u003evar SuperHeroBuilder = {\n\u003e    type: 'SuperHero',\n\u003e    build: function(context) {\n\u003e        return {\n\u003e            name: context.create('string'),\n\u003e            powers: context.createMany('string', 3),\n\u003e            age: context.create('number'),\n\u003e            hasSecretIdentity: context.create('boolean')\n\u003e        }\n\u003e    }\n\u003e}\n\u003e```\n\nWhen a builder has been added to a `Fixture` then it can be used by other builders (or in templates). Maybe - building on the hero example - the _age_ of a superhero should meet a certain criteria, i.e. value must be between 18 and 99.\n\n```js\nconst { Fixture, Builder, NumberGenerator } = require('@mixtape/core');\n\nclass SuperHeroBuilder extends Builder {\n    constructor() {\n        super('SuperHero');\n    }\n\n    build(context) {\n        return {\n            name: context.create('string'),\n            powers: context.createMany('string', 3),\n            age: context.create('HeroAge'),\n            hasSecretIdentity: context.create('boolean')\n        }\n    }\n}\n\nclass SuperHeroAgeBuilder extends Builder {\n    constructor() {\n        super('HeroAge');\n        // Use a random number generator to control the age\n        this.generator = new NumberGenerator(18, 99);\n    }\n\n    build() {\n        return this.generator.generate();\n    }\n}\n\nfixture.extensions.add(new SuperHeroBuilder());\nfixture.extensions.add(new SuperHeroAgeBuilder());\n\nconst randomHero = fixture.create('SuperHero');\n\n/**\n * Value of randomHero\n * {\n        name: '66cbacff-2e85-4403-a986-2337a28520ca',\n        powers: [\n            '4e1bab7b-2548-4fbc-9f80-e9c4f747317d',\n            '687fa7f2-250e-40fa-a561-c2ad52d91c82',\n            '3fb8e2e9-d715-4b9e-a6f2-3f6986ac0229'\n        ],\n        age: 88,\n        hasSecretIdentity: true\n    }\n  */\n```\n\nThis ensures that all generated heroes will have an age between 18 and 99.\n\n### Bundle Builders Using Extensions\n\nNow that we have two builders it would be a good idea to bundle them in an `Extension` like this\n\n```js\nconst superHeroExtension = new Extension();\nsuperHeroExtension.add(new SuperHeroBuilder());\nsuperHeroExtension.add(new SuperHeroAgeBuilder());\n\n// Now add it to a fixture like this\nconst fixture = new Fixture();\nfixture.extend(superHeroExtension);\n\n// or use it in the creation of an injector like this\nconst withHeroFixture = createInjector(() =\u003e new Fixture().extend(superHeroExtension));\n```\n\nThis makes it easy to group related builders and easily add them to Fixtures as needed.\n\n### Freeze Properties\n\nIn some test cases a number of objects need to have the same value for a specific property; this can be achieved by calling [`freeze()`](https://github.com/legaard/mixtape/wiki/The-Fixture-Class#freeze) on the `Fixture`. In this case a random sized array of heroes with same age can be created like this:\n\n```js\nfixture.freeze('HeroAge');\nconst heroesWithSameAge = fixture.createMany('SuperHero');\n\n/**\n * Value of heroesWithSameAge\n * [\n        {\n            name: '7869ced3-ff7d-4e0b-9bfb-b29d5b36d980',\n            powers: [\n                'be8f0ec5-1281-436a-9a25-3fc78086dc91',\n                '678e5e93-4bae-4b19-b75a-0b71bf43656a',\n                '8f1d9dbe-e91a-4c2e-b5f5-7d4ed270546e'\n            ],\n            age: 37,\n            hasSecretIdentity: false\n        },\n        {\n            name: '3ed5d9e5-25c3-413c-8032-60958a731414',\n            powers: [\n                '77860d28-d1b2-428e-8b1a-ded618d8314d',\n                '68429cda-f63e-48a3-88c5-f7b7fda6fdd7',\n                '102e20df-07ef-4699-87c4-c558e5a14dc4'\n            ],\n            age: 37,\n            hasSecretIdentity: true\n        },\n        {\n            name: 'f8767886-e72e-42ac-9b7d-1a4a3ccbe87a',\n            powers: [\n                '232e377e-c6d5-461f-8f52-6b3248719839',\n                'b1e45387-50de-4424-a00c-808fddb259f0',\n                'e56ca196-7515-4efd-83cd-0b5812a4e859'\n            ],\n            age: 37,\n            hasSecretIdentity: false\n        }\n        .\n        .\n        .\n    ]\n */\n```\n\n\u003e ℹ️ If the property - in our case `age` - needs to have a specific value then the method [`use()`](https://github.com/legaard/mixtape/wiki/The-Fixture-Class#use) can be utilized instead. Also, the method [`reset()`](https://github.com/legaard/mixtape/wiki/The-Fixture-Class#reset) can be used to clear all frozen values and values defined via `use()`.\n\n### Custom Objects\n\nIn other test cases a custom build object is needed and for this [`build()`](https://github.com/legaard/mixtape/wiki/The-Fixture-Class#build) can be called on the `Fixture`.\n\n```js\nconst customHero = fixture\n    .build('SuperHero')\n    .with('name', () =\u003e 'Wolverine')\n    .with('powers', p =\u003e ['healing', 'endurance', ...p])\n    .without('hasSecretIdentity')\n    .create();\n\n/**\n * Value of customHero\n * {\n        name: 'Wolverine',\n        powers: [\n            'healing',\n            'endurance',\n            'af537167-863c-42ca-8181-31f1fcb25115',\n            '250f05b4-b0ea-45c4-b0d4-2b6efbe26172',\n            '40a746c0-b361-4428-a894-86edefa61e17'\n        ],\n        age: 59\n    }\n */\n```\n\n\u003e ℹ️ Accessing a nested property is not possible using `with()`/`without()`. A way around this is to use [`do()`](https://github.com/legaard/mixtape/wiki/The-Fixture-Class#do) instead. For instance `fixture.build('type').do(t =\u003e t.nestedObject.value = 'newValue')`.\n\n## Documentation 📄\n\nMore details about this library can be found in the documentation [here](https://github.com/legaard/mixtape/wiki/Documentation).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flegaard%2Fmixtape","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flegaard%2Fmixtape","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flegaard%2Fmixtape/lists"}