Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
factory.ts
Advanced tools
A library to ease creation of factories for test data for Typescript
Given an interface or type definition, create a factory for generating test data. Values for each key may be defaulted or be calculated each time based on a sequence number and the values for other keys.
Version 0.3.0 introduces a new set of async factory methods for cases where asynchronicity is required to generate values.
interface Person {
id: number;
firstName: string;
lastName: string;
fullName: string;
age: number;
}
import * as Factory from "factory.ts";
const personFactory = Factory.Sync.makeFactory<Person>({
id: Factory.each(i => i),
firstName: "Bob",
lastName: "Smith",
fullName: "Robert J. Smith, Jr.",
age: Factory.each(i => 20 + (i % 10))
});
For each property of Person, you can specify a default value, or call Factory.Sync.each
. Factory.Sync.each
takes a lambda with a sequence number that is incremented automatically between generating instances of your type (Person
in our example).
You can call personFactory.build
with a subset of field data (Partial<Person>
) to override defaults, and the output will be an object that conforms to Person using the definition specified in makeFactory
.
const james = personFactory.build({
firstName: "James",
fullName: "James Smith"
});
// { id: 1, firstName: 'James', lastName: 'Smith', fullName: 'James Smith', age: 21 };
const youngBob = personFactory.build({ age: 5 });
// { id: 2, firstName: 'Bob', lastName: 'Smith', fullName: 'Robert J. Smith, Jr.', age: 5 };
You can also call personFactory.build
with no arguments to use factory defaults:
const anybody = personFactory.build();
And you can create an array of objects from factory using buildList
(with or without the Partial
override):
const theBradyBunch = personFactory.buildList(8, { lastName: "Brady" });
Occasionally you may want to extend an existing factory with some changes. For example, we might want to create a personFactory that emits a totally random age range:
const anyAgeFactory = personFactory.extend({
age: Factory.each(() => randomAge(0, 100)) // randomAge(min:number, max:number) => number
});
anyAgeFactory.build(); // { id: 1, ..., age: <random value> };
Extending a Factory creates a new, immutable Factory. Your initial factory remains unchanged.
One specific way to extend an existing factory is to make a new factory where one of the keys/properties is determined by other properties. For example. we can use this to specify fullName from firstName and lastName:
const autoFullNameFactory = personFactory.withDerivation2(
["firstName", "lastName"],
"fullName",
(fName, lName) => `${lName}, ${fName} ${lName}`
);
const jamesBond = autoFullNameFactory.build({
firstName: "James",
lastName: "Bond"
});
// { id: 1, firstName: 'James', lastName: 'Bond', fullName: 'Bond, James Bond', age: 21 };
The withDerivation*N*
functions consume an array of dependent key names (of length N), then the name of the property to define, then a lambda that takes the appropriate types for arguments based on the values of the dependent keys, and expects a return type that matches the derived key value type. withDerivation1
through withDerivation5
are provided. Ideally these would be overrides, but I have yet to figure out a way to make the Typescript compiler accept this.
Note that any misspelling of dependent or derived key names in a call to withDerivation*N*
will result in a compile error - aren't mapped types the best?
Alternatively, if you need to read more than 5 properties, or just don't want to specify dependencies explicitly, withDerivation
expects a property key to derive and a lambda that goes from a value of the overall type being built to a value of the type of the dependent property. For our fullName case that would be:
const autoFullNameFactory = personFactory.withDerivation(
"fullName",
person => `${person.lName}, ${person.fName} ${person.lName}`
);
Personally I prefer to be explicit about the dependent keys, but it doesn't really matter.
Derivations are processed in the order they are defined, and all withDerivation
functions produce a new immutable Factory.
Finally, you could instantiate a Derived<TOwner,TProperty>
for the value of a property inside a Factory.makeFactory
definition, but the type inference can't help you as much - you'll have to indicate the type of TOwner and TProperty.
Async factories support all the same methods as sync factories, but you can also provide generators that create Promise instead of T. Consequently each property may or may not use asynchronicity for generation, but the final factory requires only one await.
transform()
Async factories also have a transform()
method which can take a function that goes from T => U
or from T => Promise<U>
. This creates an object with the factory interface for building only, and is meant to be a "last step" transform. The idea is that the output of the last step may be a different type. For example, you may have an Unsaved and a Saved type for database records, so you can pass in your insert(u: Unsaved): Promise<Saved>
method and get a factory which will asynchronously build a persisted Saved
object.
FAQs
A Typescript test data factory similar to factory_bot and rosie
The npm package factory.ts receives a total of 140,646 weekly downloads. As such, factory.ts popularity was classified as popular.
We found that factory.ts demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers 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
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.