When testing front-end applications you often need to initialize components, and create mock data matching your back-end. Instead of having to do repeat this process in every test, this library will provide you with a set of utilities for bootstrapping your tests without boilerplate and facilitate efficient data-driven API mocking.
- @testing-initializer/react: Testing bootstrapping utilities for React. This library
contains
@testing-initializer/data
. So, if you are using React, I recommend installing only this package. - @testing-initializer/data: Wrapper around @msw/data that allows for typed data modelling and relation on a mocked database.
This package contains all necessary utilities for bootstrapping React components in your tests.
npm i @testing-initializer/data
or with Yarn:
yarn add @testing-initializer/react
First, let's create our mock database:
import { createDatabase, generateId } from "@testing-initializer/react"
interface User {
id: number
name: string
}
interface ToDo {
id: number
name: string
}
interface Project {
id: number
name: string
date: string
user: User
toDos: ToDo[]
}
interface APITypes {
user: User
toDo: ToDo
project: Project
}
const db = createDatabase<APITypes>({
user: {
id: () => generateId("user-pk"),
name: () => `User ${generateId("user-name")}`,
},
toDo: {
id: () => generateId("toDo-pk"),
name: () => `Todo ${generateId("toDo-name")}`,
},
project: {
id: () => generateId("project-pk"),
date: () => new Date().toISOString(),
name: () => `Project ${generateId("project-name")}`,
user: oneOf("user"),
toDos: manyOf("toDo"),
},
})
Now, let's say we have the following component:
interface TestComponentProps {
project: Project
}
const TestComponent = ({ project }: TestComponentProps) => {
return (
<div>
<p>{project.user.name}</p>
<p>{project.name}</p>
<div>
{project.toDos.map(({ id, name }) => (
<p key={id}>{name}</p>
))}
</div>
</div>
)
}
We can now proceed to create a renderer, a reusable function that renders your component with its necessary props:
import { createRenderer, createDatabase, generateId } from "@testing-initializer/react"
...
const renderTestComponent = createRenderer()
.addData("currentUser", () => db.user.create())
.addData("toDos", () => [db.toDo.create(), db.toDo.create(), db.toDo.create()])
.setProps(({ currentUser, toDos }) => ({
project: db.project.create({ toDos, user: currentUser }) as unknown as Project,
currentUser,
toDos,
}))
.setComponent(TestComponent)
.setRenderFunction(render)
.build()
Notice the data
property. These extra properties are useful for getting generated data outside of the component props.
With this renderer, we can render our components consistently within tests:
it("...", () => {
const { project, currentUser, toDos } = renderTestComponent()
})
We can also render override its data
or props
:
it("...", () => {
renderTestComponent({
data: {
currentUser: db.user.create({ name: "User override" }),
},
})
})
This package allows you to create a @msw/data type-safe database. It will read nested
arrays as a many of
relationship and objects as a one of
relationship.
npm i @testing-initializer/data
or with Yarn:
yarn add @testing-initializer/data
First make you have your types available:
interface User {
id: number
name: string
}
interface ToDo {
id: number
name: string
}
interface Project {
id: number
name: string
date: string
user: User
toDos: ToDo[]
}
interface APITypes {
user: User
toDo: ToDo
project: Project
}
Proceed to create your mock database based on this types.
import { createDatabase, generateId } from "@testing-initializer/data"
const db = createDatabase<APITypes>({
user: {
id: () => generateId("user-pk"),
name: () => `User ${generateId("user-name")}`,
},
toDo: {
id: () => generateId("toDo-pk"),
name: () => `Todo ${generateId("toDo-name")}`,
},
project: {
id: () => generateId("project-pk"),
date: () => new Date().toISOString(),
name: () => `Project ${generateId("project-name")}`,
user: oneOf("user"),
toDos: manyOf("toDo"),
},
})
Now you can use all database methods available in @msw/data:
db.user.create()
db.user.findFirst({ ... })
db.project.findMany({ ... })