Mocks
Conventions
- Each mocked entity should have the same name as the original entity, prefixed with "Mock". Example:
MockEmailAddress
. - Each mock function should take an
overrides
object which allows passing predefined data to the mock.
Note: this only applies to mocks for "object" types - TODO: Each mock function should accept a second argument for specifying the
seed
- When a property from "EntityA" references "EntityB", the mock for that property should just call the mock generator for "EntityB" (if available). See the examples below.
Example
Here's a concrete example of implementing mocks for a few entities.
Diagram
Type Definitions
info
The data models used in this example are not real. For brevity reasons, most of the fields are omitted.
export interface ActivityFeedItem {
eventType: string;
createdAt: number;
updatedAt: number;
}
export interface MessageEvent extends ActivityFeedItem {
content: string;
direction: "INBOUND" | "OUTBOUND";
eventType: "message_event";
}
export declare type EmailAddress = {
name: string;
address: string;
};
export declare type EmailBaseAttributes = {
senderEmail: EmailAddress;
toEmails: EmailAddress[];
subject: string;
threadId: string;
messageId: string;
bodySnippet: string;
name: "Email Sent" | "Email Received";
direction: "inbound" | "outbound";
};
export interface EmailEvent extends EmailBaseAttributes, ActivityFeedItem {
eventType: "email";
}
export interface EmailSentEvent extends EmailEvent {
name: "Email Sent";
direction: "outbound";
}
export interface EmailReceivedEvent extends EmailEvent {
name: "Email Received";
direction: "inbound";
}
export interface EmailThread {
eventType: "email-thread";
threadId: string;
events: Array<EmailSentEvent | EmailReceivedEvent>;
}
export type ActivityFeedItemLike =
| MessageEvent
| EmailSentEvent
| EmailReceivedEvent
| EmailThread;
Mocks
MockActivityFeedItem
export function MockActivityFeedItem(
overrides: Partial<ActivityFeedItem> = {}
): ActivityFeedItem {
const result = {
eventType: faker.word.words(),
createdAt: new Date(faker.date.recent()).getTime(),
updatedAt: new Date(faker.date.recent()).getTime(),
};
return { ...result, ...overrides };
}
MockMessageEvent
export function MockMessageEvent(
overrides: Partial<MessageEvent> = {}
): MessageEvent {
const result = {
...MockActivityFeedItem(),
content: faker.word.words(),
direction: faker.helpers.arrayElement(["INBOUND", "OUTBOUND"]),
eventType: "message_event",
};
return { ...result, ...overrides };
}
MockEmailAddress
export function MockEmailAddress(
overrides: Partial<EmailAddress> = {}
): EmailAddress {
const result = {
name: faker.person.fullName(),
address: faker.internet.email(),
};
return { ...result, ...overrides };
}
MockEmailBaseAttributes
export function MockEmailBaseAttributes(
overrides: Partial<EmailBaseAttributes> = {}
): EmailBaseAttributes {
const result = {
senderEmail: MockEmailAddress(),
toEmails: faker.helpers.multiple(() => MockEmailAddress()),
subject: faker.word.words(),
threadId: faker.string.alpha(34),
messageId: faker.string.alpha(34),
bodySnippet: faker.word.words(),
name: faker.helpers.arrayElement(["Email Sent", "Email Received"]),
direction: faker.helpers.arrayElement(["inbound", "outbound"]),
};
return { ...result, ...overrides };
}
MockEmailEvent
export function MockEmailEvent(
overrides: Partial<EmailEvent> = {}
): EmailEvent {
const result = {
...MockEmailBaseAttributes(),
...MockActivityFeedItem(),
eventType: "email",
};
return { ...result, ...overrides };
}
MockEmailSentEvent
export function MockEmailSentEvent(
overrides: Partial<EmailSentEvent> = {}
): EmailSentEvent {
const result = {
...MockEmailEvent(),
name: "Email Sent",
direction: "outbound",
};
return { ...result, ...overrides };
}
MockEmailReceivedEvent
export function MockEmailReceivedEvent(
overrides: Partial<EmailReceivedEvent> = {}
): EmailReceivedEvent {
const result = {
...MockEmailEvent(),
name: "Email Received",
direction: "inbound",
};
return { ...result, ...overrides };
}
MockEmailThread
export function MockEmailThread(
overrides: Partial<EmailThread> = {}
): EmailThread {
const result = {
eventType: "email-thread",
threadId: faker.string.alpha(34),
events: faker.helpers.multiple(() =>
faker.helpers.arrayElement([
MockEmailSentEvent(),
MockEmailReceivedEvent(),
])
),
};
return { ...result, ...overrides };
}
MockActivityFeedItemLike
export function MockActivityFeedItemLike(
overrides: Partial<ActivityFeedItemLike> = {}
): ActivityFeedItemLike {
const result = faker.helpers.arrayElement([
faker.helpers.arrayElement([
MockMessageEvent(),
MockEmailSentEvent(),
MockEmailReceivedEvent(),
MockEmailThread(),
]),
]);
return { ...result, ...overrides };
}
Usage
Defaults
const randomMessageEvent = MockMessageEvent();
const randomEmailThread = MockEmailThread();
// returns one of MessageEvent, EmailSentEvent, EmailReceivedEvent or EmailThread
const randomActivityFeedItemLike = MockActivityFeedItem();
Overrides
Properties
const messageEvent = MockMessageEvent({
content: "Hardcoded message for this particular test",
});
Nested properties
If you need more control of the threads, for example making sure the sender
and to
email addresses are correct:
const agentEmail: EmailAddress = {
name: "Michael Scott",
address: "michael.scott@regal.io",
};
const contactEmail: EmailAddress = {
name: "Holly Flax",
address: "holly.flax@gmail.com",
};
const emailThread = MockEmailThread({
events: [
MockEmailSentEvent({ senderEmail: agentEmail, toEmails: [contactEmail] }),
MockEmailReceivedEvent({
senderEmail: contactEmail,
toEmails: [agentEmail],
}),
],
});