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

@nickglenn/mongo-seeder

v2.0.1

Published

Test utility for seeding MongoDB with application data.

Downloads

8

Readme

NodeJS Mongo Seeders for Testing

This library provides methods for quickly creating utilities for inserting seeded data into MongoDB for testing purposes. It supports several methods for inserting one to many rows, applying "patch" data on top of seed generated data, and clean up for seeded data.

Getting Started

Install the library via npm. It's recommended that you install this as a development dependency.

npm i -D @nickglenn/mongo-seeder

Once installed, you can start integrating it by creating a "seeder map". This requires an object where the key represents a collection in your database, and the value is a factory function that returns the data necessary for a single document. It's recommended that you randomize the data output from each factory function in the map as this will help to create more robust tests.

Note: In the example below, we use the faker library to create some randomized data for our tests.

import { createSeederMap } from "@nickglenn/mongo-seeder";
import * as faker from "faker";

export const setupSeeders = createSeederMap({
  users: () => ({
    email: faker.internet.email(),
    password: faker.internet.password(),
  }),
  posts: () => ({
    title: faker.lorem.words(3),
    content: faker.lorem.sentences(5),
    published: faker.random.boolean(),
  }),
});

Now let's add it to our test suite. The createSeederMap function returned another function that needs us to provide an instance of a Mongo Database class. Once we've done that, we can begin using our seeders in some tests.

Note: The following syntax is what you'd likely see in a Jest or Mocha suite.

import * as mongo from "mongodb";
import { setupSeeders } from "./mySeeders";
import { findUserByEmail } from "./some/path/in/app";

let seeders;

beforeAll(async () => {
  // connect to mongodb
  const conn = await mongo.connect("mongodb://localhost/testing");

  // instantiate our seeders
  seeders = setupSeeders(conn.db());
});

afterEach(async () => {
  // after each test we can destroy all seeded data generated by each test
  await seeders.clean();
});

it("correctly fetches a user based on email", async () => {
  // use any of the seeder methods to insert some test records
  const testUser = await seeders.users.one();

  // run your code
  const fetchedUser = await findUserByEmail(testUser.email);

  // perform assertions
  expect(testUser._id.equals(fetchedUser._id)).toBe(true);
});

Seed Patching

type SeedPatcher<T> = Partial<T> | (generated: T, index: number) => T;

All of the methods for inserting seeds into the database support "seed patching". This allows generated records to be augmented in order to support specific test case scenarios.

Patch via Object

Patching seeds using an object performs a deep merge of the patch value on top of the generated value. This allows you to override the generated data before it's put into the database.

Using the example from above, we could alter our test to use a specific email address.

it("correctly fetches a user based on email", async () => {
  // use any of the seeder methods to insert some test records
  const testUser = await seeders.users.one({ email: "[email protected]" });

  // run your code
  const fetchedUser = await findUserByEmail("[email protected]");

  // perform assertions
  expect(testUser._id.equals(fetchedUser._id)).toBe(true);
});

Patch via Function

Sometimes a bit more flexibility is needed for testing scenarios. A patching function is called with the generated seed value (and numeric index) and the returned value is what will be stored in the database before being returned.

it("correctly fetches a user based on email from a larger pool of users", async () => {
  // create 5 user records, but only the second record will have the test email
  const testUsers = await seeders.users.many(5, (user, index) => {
    if (index === 1) {
      return { ...user, email: "[email protected]" };
    }
    return user;
  });

  // run your code
  const fetchedUser = await findUserByEmail("[email protected]");

  // perform assertions
  expect(testUsers[0]._id.equals(fetchedUser._id)).toBe(false);
  expect(testUsers[1]._id.equals(fetchedUser._id)).toBe(true);
  expect(testUsers[2]._id.equals(fetchedUser._id)).toBe(false);
  expect(testUsers[3]._id.equals(fetchedUser._id)).toBe(false);
  expect(testUsers[4]._id.equals(fetchedUser._id)).toBe(false);
});

Seeder Methods

one

Seeder<T>.one(patch?: SeedPatcher<T>): Promise<T>;

Creates and inserts a single record into the database, returning the inserted record.

many

Seeder<T>.many(count: number, patch?: SeedPatcher<T>): Promise<T[]>;

Creates and inserts 1-n records into the database, returning the inserted records as an array. The argument count cannot be less than 1 and must be an integer value.

random

Seeder<T>.random(min: number, max: number, patch?: SeedPatcher<T>): Promise<T[]>;

Creates and inserts a random number of records (within the given range) into the database, returning the inserted records as an array. The min argument must be 0 or greater and the max argument must be 1 greater than min.

pick

Seeder<T>.pick(min: number, max: number, patch: SeedPatcher<T>): Promise<[ T, T[] ]>;

An amalgamation of the other seeder records, pick actually requires that a seed patcher be provided. This is because pick will create a random number of records (within the given range) and insert them into the database However, a randomly selected record will be selected as the standout and will be patched, while the other records will not be patched and are stored in a crowds array.

This is useful for testing operations that may have differing results based on the amount of "noise" in the database.

const [standout, crowd] = await seeder.users.pick(min: 2, max: 20, { email: "[email protected]" });

clean

Seeder<T>.clean(): Promise<void>;

Deletes all inserted records created by the seeder instance.