Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Fishery is a JavaScript library for creating test data. It allows you to define factories for your data models, making it easy to generate consistent and realistic test data for your applications.
Defining a Factory
This feature allows you to define a factory for a data model. In this example, a factory for a user model is defined with an id, name, and email. The `sequence` function ensures that each generated user has a unique id and email.
const { Factory } = require('fishery');
const userFactory = Factory.define(({ sequence }) => ({
id: sequence,
name: `User ${sequence}`,
email: `user${sequence}@example.com`
}));
const user = userFactory.build();
console.log(user);
Building Multiple Instances
This feature allows you to generate multiple instances of a model. In this example, three user instances are generated using the `buildList` method.
const users = userFactory.buildList(3);
console.log(users);
Customizing Instances
This feature allows you to customize the generated instances. In this example, a user instance is generated with a custom name while other attributes are generated by the factory.
const customUser = userFactory.build({ name: 'Custom User' });
console.log(customUser);
Associations
This feature allows you to define associations between different models. In this example, a post model is defined with an associated user model as the author.
const postFactory = Factory.define(({ sequence }) => ({
id: sequence,
title: `Post ${sequence}`,
author: userFactory.build()
}));
const post = postFactory.build();
console.log(post);
Faker is a popular library for generating fake data. It provides a wide range of data types and formats, making it versatile for various use cases. Unlike Fishery, Faker does not focus on defining factories for data models but rather on generating random data directly.
Factory-girl is a library for defining and building factories for JavaScript objects. It is similar to Fishery in that it allows you to define factories for your data models. However, Fishery offers a more modern API and better TypeScript support.
Rosie is another factory library for JavaScript. It allows you to define factories and build objects with complex relationships. Compared to Fishery, Rosie has a more verbose API and less intuitive syntax.
This project is still in early stages. Prior to a 1.0 release, its API is subject to change without notice.
Fishery is a library for setting up JavaScript objects for use in tests, Storybook, and anywhere else you need to set up data. It is modeled after the Ruby gem, factory_bot.
Fishery is built with TypeScript in mind. Factories return typed objects, so you can be confident that the data used in your tests is valid. If you aren't using TypeScript, that's fine too – Fishery still works, just without the extra typechecking that comes with TypeScript.
First, install fishery with:
npm install --save fishery
or
yarn add fishery
It is recommended to define one factory per file and then combine them together to form a factories
object which can then be used in tests, Storybook, etc.:
// factories/user.ts
import { Factory } from 'fishery';
import { User } from '../my-types';
export default Factory.define<User>(({ sequence }) => ({
id: sequence,
name: 'Bob',
}));
Now combine your factories together and register them:
// factories/index.ts
import { register } from 'fishery';
import user from './user';
import post from './post';
export const factories = register({
user,
post,
});
// my-test.test.ts
import { factories } from './factories';
const user = factories.user.build({ name: 'Susan' });
Factories are typed, so using the factory from the above example, these would both cause TypeScript compile errors:
const user = factories.user.build();
user.foo; // type error! Property 'foo' does not exist on type 'User'
const user = factories.user.build({ foo: 'bar' }); // type error! Argument of type '{ foo: string; }' is not assignable to parameter of type 'Partial<User>'.
If your factory references another factory, use the factories
object provided by the generator function:
const postFactory = Factory.define<Post, Factories>(
({ factories, params }) => ({
title: 'My Blog Post',
author: params.author || factories.user.build(),
}),
);
There are two things to note in the example above:
factories
and the Factories
type parameterIn the above example, we used factories
which is supplied by the factory generator function. Using the factories object helps avoid circular import issues where two factories need to reference each other. The factories
object represents the combined factories object that was supplied to register
when setting up Fishery. To get type-checking of factories
, a second type parameter should be passed to Factory.define
, called Factories
. The type should be defined like:
export interface Factories {
user: Factory<User>;
post: Factory<Post>;
}
params
to access passed in propertiesIn the above postsfactory
example, the author property is calculated as author: params.author || factories.user.build()
. The params
object represents the properties bassed to the factory's build
method. With this definition, if we create a post with postsFactory.build({ author })
, then factories.user.build()
is conveniently not executed. This can be handy in preventing infinite loops or expensive operations.
It is important to note that if the user factory has a call to factories.post.build()
(without specifying the author), an infinite loop would still occur. The user factory would need to either not automatically create a post or pass itself as the author in an afterCreate
, like:
const userFactory = Factory.define<User, Factories>(
({ factories, afterCreate }) => {
afterCreate(user => user.posts.push(factories.post.build({ author: user })));
return {
name: 'Bob',
posts: [],
};
},
);
In normal situations, you should not have to access params
directly. The properties passed in to build
are automatically overlaid on top of the default properties defined by the factory.
You can instruct factories to execute some code after an object is created. This can be useful if a reference to the object is needed, eg. when setting up relationships:
export default Factory.define<User, Factories>(({ factories, sequence, afterCreate }) => {
afterCreate(user => {
if(user.posts.length === 0) {
user.posts.push(factories.post.build({ author: user })
}
});
return {
id: sequence,
name: 'Bob',
posts: []
};
});
See the CONTRIBUTING document. Thank you, contributors!
This project name was inspired by Patrick Rothfuss' Kingkiller Chronicles books. In the books, the artificery, or workshop, is called the Fishery for short.
Fishery is Copyright © 2019 Stephen Hanson and thoughtbot. It is free software, and may be redistributed under the terms specified in the LICENSE file.
Fishery is maintained and funded by thoughtbot, inc. The names and logos for thoughtbot are trademarks of thoughtbot, inc.
We love open source software! See our other projects or hire us to design, develop, and grow your product.
FAQs
A library for setting up JavaScript factories to help build objects as test data, with full TypeScript support
The npm package fishery receives a total of 201,617 weekly downloads. As such, fishery popularity was classified as popular.
We found that fishery demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.