Tutorial
Let's discover [mocq]
in less than 5 minutes
Getting Started
For this tutorial we will be working with these two types User
and Node
- JavaScript
- TypeScript
type User = {
username: string
email: string
};
type Node = {
name: string
createdBy: string
};
export type User = {
username: string
email: string
};
export type Node = {
name: string
createdBy: string
};
In this contrived example Nodes
are created by Users
The goal of this tutorial will be:
- generate mock
Users
&Nodes
- connect
Node
data withUser
data, ensuring everyNode
is created by a validUser
in our data set - explore using handlers to do something with this resolved data
Generating Data
First we'll define some data generator functions
- JavaScript
- TypeScript
export const generateMockUser = (i) => {
const username = `user_${i}`;
return {
username,
email: `${username}@email.com`,
};
};
export const generateMockNode = (i) => ({
name: `node_${i}`,
createdBy: 'unknown',
});
export function generateMockUser (i: number): User {
const username = `user_${i}`;
return {
username,
email: `${username}@email.com`,
};
};
export function generateMockNode (i: number): Node {
return: {
name: `node_${i}`,
createdBy: 'unknown',
};
};
These functions create a singe instance
of Node
& User
type, and are handed index
for use with uniqueness
Now we define our configuration object, we'll make 25 Users
and 100 Nodes
using the generator functions we wrote above
We'll use the configuration key names users
and nodes
for our User
and Node
data type configurations to maintain context
- JavaScript
- TypeScript
import { mocq } from 'mocq';
import { generateMockUser, generateMockNode } from './generators';
const config = {
users: {
generator: generateMockUser,
count: 25,
},
nodes: {
generator: generateMockNode,
count: 100,
},
};
const { generate } = mocq(config);
const { data: { users, nodes } } = generate();
import { mocq, MocQ } from 'mocq';
import { User, Node } from './types';
import { generateMockUser, generateMockNode } from './generators';
// create a custom config type for strict type checking
type customMocqConfig = {
users: MocQ<User>
nodes: MocQ<Node>
};
const config: customMocqConfig = {
users: {
generator: generateMockUser,
count: 25,
},
nodes: {
generator: generateMockNode,
count: 100,
},
};
const { generate } = mocq(config);
const { data: { users, nodes } } = generate();
Sample Resolved Data
users
:
[
{
username: 'user_0'
email: 'user_0@email.com'
},
// ... 24 more entries
]
nodes
:
[
{
name: 'node_0'
createdBy: 'unkown'
},
// ... 99 more entries
]
Connecting Data
Now we'll define our connection function, this function will assign a random User
username to the createdBy
value for each Node
- JavaScript
- TypeScript
export const userCreatedNodeConnection = (users) => {
const randomIndex = Math.floor(Math.random() * users.length);
return {
createdBy: users[randomIndex].username,
};
};
import { User, Node } from './types';
export function userCreatedNodeConnection (data: User[]): Partial<Node> {
const randomIndex = Math.floor(Math.random() * data.length);
return {
createdBy: data[randomIndex].username,
};
};
Again this function is utilized at the instance level
, we are given the resolved data from the users
config
we also have access to the
index
and thedata
of the currentNode
instance being manipulated however those won't be needed in our example (see API for full spec)
Let's add the connection to the nodes
configuration under connections
with the key users
to enable the function to hook into the users
config resolved data
- JavaScript
- TypeScript
import { mocq } from 'mocq';
import { generateMockUser, generateMockNode } from './generators';
import { userCreatedNodeConnection } from './connections';
const config = {
users: {
generator: generateMockUser,
count: 25,
},
nodes: {
generator: generateMockNode,
count: 100,
connections: {
users: userCreatedNodeConnection,
};
},
};
const { generate } = mocq(config);
const { data: { users, nodes } } = generate();
import { mocq, MocQ } from 'mocq';
import { User, Node } from './types';
import { generateMockUser, generateMockNode } from './generators';
import { userCreatedNodeConnection } from './connections';
// create a custom config type for strict type checking
type customMocqConfig = {
users: MocQ<User>
nodes: MocQ<Node>
};
const config: customMocqConfig = {
users: {
generator: generateMockUser,
count: 25,
},
nodes: {
generator: generateMockNode,
count: 100,
connections: {
users: userCreatedNodeConnection,
};
},
};
const { generate } = mocq(config);
const { data: { users, nodes } } = generate();
Sample Resolved Data
users
:
[
{
username: 'user_0'
email: 'user_0@email.com'
},
// ... 24 more entries
]
nodes
:
[
{
name: 'node_0'
createdBy: 'user_7'
},
{
name: 'node_1'
createdBy: 'user_3'
},
// ... 98 more entries
]
Handling Resolved Data
Our data is now generating correctly
In our simple example it's very easy to see that Users
need to be defined before Nodes
in order for
the createdBy
field to properly reference generated Users
However for larger data sets with many types of objects this order of operations might not be as apparent
That's where handlers come in to play, allowing you to execute a function against resloved data utilizing the derived execution order used to generate the data
Meaning whether you're writing this data to a database, calling an api, or whatever; handler functions will be executed in an order allowing parent data to be defined 1st enabling data to seemless flow into your data store
In this example we will simply log the output with our handler function
handler functions can be sync
or async
- JavaScript
- TypeScript
export const logHandler = (data) => {
data.map(x => console.log(x));
};
export function logHandler (data: any[]): void {
data.map(x => console.log(x));
};
Now lets add this handler to our configuration
we'll flip the order of our configuration keys to show the execution order coordination in action
- JavaScript
- TypeScript
import { mocq } from 'mocq';
import { generateMockUser, generateMockNode } from './generators';
import { userCreatedNodeConnection } from './connections';
import { logHandler } from './handlers';
const config = {
nodes: {
generator: generateMockNode,
count: 100,
connections: {
users: userCreatedNodeConnection,
};
handler: logHandler,
},
users: {
generator: generateMockUser,
count: 25,
handler: logHandler,
},
};
const { execute } = mocq(config);
const { data: { users, nodes } } = await execute();
import { mocq, MocQ } from 'mocq';
import { User, Node } from './types';
import { generateMockUser, generateMockNode } from './generators';
import { userCreatedNodeConnection } from './connections';
import { logHandler } from './handlers';
// create a custom config type for strict type checking
type customMocqConfig = {
nodes: MocQ<Node>
users: MocQ<User>
};
const config: customMocqConfig = {
nodes: {
generator: generateMockNode,
count: 100,
connections: {
users: userCreatedNodeConnection,
};
handler: logHandler,
},
users: {
generator: generateMockUser,
count: 25,
handler: logHandler,
},
};
const { execute } = mocq(config);
const { data: { users, nodes } } = await execute();
Sample Output
{
username: 'user_0'
email: 'user_0@email.com'
}
{
username: 'user_1'
email: 'user_1@email.com'
}
// ... 23 more entries
{
name: 'node_0'
createdBy: 'user_18'
}
{
name: 'node_1'
createdBy: 'user_2'
}
// ... 98 more entries