npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@spencejs/spence-factories

v0.10.2

Published

Spence Factories - An opinionated Factory Framework for testing db entities

Downloads

1,265

Readme

Spencejs: Factories

Test Factories is engineering applied to managing your data. Factories make it easy to create, manage, reuse & extend data sets needed for making great integration & e2e tests

Data can be either generated for creation tests, or persisted to databases. Mocks, which look like persisted data but are not added to any database are also supported.

Getting started

Lets say you have a user object like this

{
    firstName: "Fred",
    lastName: "Astaire",
    dob: "1899-05-10"
}

Your first factory can be defined in a file like this

// user-factory.js
const { register } = require("@spencejs/spence-factories");
const userRepo = require("./user-repo");
module.exports = register("user", userRepo, (overrides) => ({
    firstName: "Fred",
    lastName: "Astaire",
    dob: "1899-05-10",
    ...overrides()
}));

In your test classes you can then use

const { newUser, createdUser, persistUser } = require("./user-factory.js");

Create a new user to send in a payload

  const user = newUser()
  //{
  //  firstName: "Fred",
  //  lastName: "Astaire",
  //  dob: "1899-05-10"
  //}

You can use overrides to change the data for a specific test

   const user = newUser({lastName: "Rodgers"});
   //{
   //  firstName: "Fred",
   //  lastName: "Rodgers",
   //  dob: "1899-05-10"
   //}   

You can even persist into the database

   const user = await persistUser({lastName: "Rodgers"});
   //{
   //  _id: ObjectID("507f191e810c19729de860ea"),
   //  firstName: "Fred",
   //  lastName: "Rodgers",
   //  dob: "1899-05-10",
   //  createdAt: Date(2020-06-22T17:55:32Z)
   //  updatedAt: Date(2020-06-22T17:55:32Z)
   //} 
   
   const dbUser = await userRepo.findById(user._id);
   //{
   //  _id: ObjectID("507f191e810c19729de860ea"),
   //  firstName: "Fred",
   //  lastName: "Rodgers",
   //  dob: "1899-05-10",
   //  createdAt: Date(2020-06-22T17:55:32Z)
   //  updatedAt: Date(2020-06-22T17:55:32Z)
   //} 

You can use mock persisted data that creates data that conforms to what it would look like if persisted, but doesnt actually persist anything. These are useful for when stubbing out api calls to apis or microservices.

   const user = await createdUser({lastName: "Rodgers"});
   //{
   //  _id: ObjectID("507f191e810c19729de860ea"),
   //  firstName: "Fred",
   //  lastName: "Rodgers",
   //  dob: "1899-05-10",
   //  createdAt: Date(2020-06-22T17:55:32Z)
   //  updatedAt: Date(2020-06-22T17:55:32Z)
   //}   
   
   const dbUser = await userRepo.findById(user._id);
   // throws Not found error

Nested Documents & Relationships

Nested Documents

More complex object graphs describe relationships that exist in the data that is persisted. Factories allow you to specify these relationships once only. spence supports creating the graphs as follows:

const { register } = require("@spencejs/spence-factories");
const userFactory = require("./user-factory");
const groupRepo = require("./group-repo");
module.exports = register("group", groupRepo, (overrides, { getOrBuild }) => ({
    name: "Dancing Stars",
    admin: await getOrBuild("admin", userFactory),
    ...overrides()
}));

Such a factory allows you build complex objects as easily as

const { newUser, createdUser, persistUser } = require("./user-factory.js");
const { newGroup, createGroup, persistGroup } = require("./group-factory.js");

async function examples() {
  const group = await newGroup() // NOTE: newGroup must now use async/await
  //{
  //  name: "Dancing Stars"
  //  admin: { firstName: "Fred", lastName: "Astaire", dob: "1899-05-10" }
  // }

  const mockGroup = await createdGroup();
  //{
  //  _id: ObjectID("507f191e810c19729de860ea"),
  //  name: "Dancing Stars"
  //  admin: { _id: ObjectID("5efb07ac9baa66d86149b695"), firstName: "Fred", lastName: "Astaire", dob: "1899-05-10", createdAt: Date(2020-06-22T17:55:32Z), updatedAt: Date(2020-06-22T17:55:32Z) },
  //  createdAt: Date(2020-06-22T17:55:32Z)
  //  updatedAt: Date(2020-06-22T17:55:32Z)
  // }

  const dbGroup = await persistGroup();
  //{
  //  _id: ObjectID("5efb07b7c2bb549ef5611262"),
  //  name: "Dancing Stars"
  //  admin: { _id: ObjectID("5123f19112319f729de860df"), firstName: "Fred", lastName: "Astaire", dob: "1899-05-10", createdAt: Date(2020-06-22T17:55:32Z), updatedAt: Date(2020-06-22T17:55:32Z) },
  //  createdAt: Date(2020-06-22T17:55:32Z)
  //  updatedAt: Date(2020-06-22T17:55:32Z)
  // }

Overriding is of course supported

const admin = newUser({ firstName: "Lucille", lastName: "Ball", dob: "1911-08-06" })
const group = newGroup({ admin });

//{
//  _id: ObjectID("5efb0911c425921f99415f33"),
//  name: "Dancing Stars"
//  admin: { _id: ObjectID("5efb09096d38f572cf104a03"), firstName: "Lucille", lastName: "Ball", dob: "1911-08-06", createdAt: Date(2020-06-22T17:55:32Z), updatedAt: Date(2020-06-22T17:55:32Z) },
//  createdAt: Date(2020-06-22T17:55:32Z)
//  updatedAt: Date(2020-06-22T17:55:32Z)
// }
}

Modelling foreign keys

const { register } = require("@spencejs/spence-factories");
const userFactory = require("./user-factory");
const groupRepo = require("./group-repo");
const groupFactory = register("group", groupRepo, (overrides, { getOrBuild }) => ({
    name: "Dancing Stars",
    adminId: (await getOrBuild("admin", userFactory)).id,
    ...overrides()
}));

async function testData() {
  const dbGroup = await persistGroup();
  //{
  //  _id: ObjectID("5efb07b7c2bb549ef5611262"),
  //  name: "Dancing Stars"
  //  admin: ObjectID("5123f19112319f729de860df"),
  //  createdAt: Date(2020-06-22T17:55:32Z)
  //  updatedAt: Date(2020-06-22T17:55:32Z)
  // }

  const dbUser = await userRepo.findById(dbGroup._id);
  //{
  //  _id: ObjectID("507f191e810c19729de860ea"),
  //  firstName: "Fred",
  //  lastName: "Astaire",
  //  dob: "1899-05-10",
  //  createdAt: Date(2020-06-22T17:55:32Z)
  //  updatedAt: Date(2020-06-22T17:55:32Z)
  //} 
}