mswjs / data

Data modeling and relation library for testing JavaScript applications.
https://npm.im/@mswjs/data
MIT License
827 stars 52 forks source link

Support global "reset" capability #134

Closed kentcdodds closed 3 years ago

kentcdodds commented 3 years ago

I want to keep all my tests completely isolated. This means I need the ability to drop all values in every database:

import {dropAll} from '@mswjs/data'

afterEach(() => dropAll())

I would use that in my global test configuration so every test could be completely isolated.

kettanaito commented 3 years ago

Hey, @kentcdodds.

As each mock database is isolated I'm not sure if exposing a method that'd magically drop them all would be a good idea.

At the moment you can utilize drop that operates on a single database and implement the dropAll by yourself:

// jest.setup.js
import { drop } from '@mswjs/data'
import * as databases from './mock/db'

afterEach(() => {
  databases.forEach(db => drop(db))
})
// mock/db.js
import { factory } from '@mswjs/data'

export const one = factory({...})
export const two = factory({...})

It's worth mentioning that multi-db setup is rather uncommon. I think the need to reset multiple DB may come from your modeling requirements where you wish to model standalone pieces of data using this library. That's not yet supported and we should look into this in the future.

At the moment each factory represents a queriable model dictionary, which is more suitable for internal/external data representation (i.e. the data you send/fetch from various endpoints) rather than for static fixtures. If you think of it this way, you'd rarely need more than one mock database.

kentcdodds commented 3 years ago

I guess what I'm thinking about is the situation where you only need a certain database in a single test file. In that situation I don't want to worry about extracting that to a separate file or including it in the app-wide test database. And I'd also like to not have to worry about adding the drop afterEach. But maybe it's not that big of a deal to remember to do that.

kettanaito commented 3 years ago

If you're using a single database in a single test file and wish for the tests to start from the clean state of the database, use drop.

// my.test.js
import { factory, drop } from '@mswjs/data'

const db = factory({ user: {...} })

afterEach(() => {
  drop(db)
})

test('one', () => {
  db.user.create({ firstName: 'John' })
})

test('two', () => {
  db.user.findFirst({ where: { firstName: { equals: 'John' } } })
  // null, no user has been created in this test.
})

drop deletes all the records for all the models in the database.

kentcdodds commented 3 years ago

Yeah, I guess all I was hoping to do was avoid having to do this in every file that creates a new factory:

afterEach(() => {
  drop(db)
})

Not a big deal I think.

kettanaito commented 3 years ago

I'd favor explicitness but understand your concerns about the repeated testing setup.