Specialized utilities for mocking array and list fields with controlled length and content generation. Essential for creating realistic GraphQL list responses with variable lengths and custom data generation.
Core class for generating arrays with controlled length and optional mock functions.
/**
* Generate arrays with specified length and optional mock function
*/
class MockList {
/**
* Create a MockList instance
* @param length - Fixed number or range [min, max] for array length
* @param mockFunction - Optional function to generate each array item
*/
constructor(length: number | Array<number>, mockFunction?: () => unknown);
/**
* Generate the mocked array
* @returns Array of mocked values
*/
mock(): Array<unknown>;
}Usage Examples:
import { MockList, addMocksToSchema } from "@graphql-tools/mock";
// Fixed length lists
const fixedList = new MockList(5); // Always 5 items
const rangeList = new MockList([2, 8]); // Random between 2-8 items
// Lists with custom item generation
const customList = new MockList(3, () => ({
id: Math.random().toString(36).substr(2, 9),
name: ['Alice', 'Bob', 'Charlie'][Math.floor(Math.random() * 3)]
}));
// In schema mocks
const mockedSchema = addMocksToSchema({
schema,
mocks: {
User: () => ({
posts: () => new MockList([1, 10], () => ({
title: 'Sample Post Title',
content: 'Sample content...'
})),
tags: () => new MockList(3, () =>
['javascript', 'graphql', 'react', 'nodejs'][Math.floor(Math.random() * 4)]
),
followers: () => new MockList([0, 1000]) // Just count, items mocked elsewhere
})
}
});Utility functions for identifying and working with MockList instances.
/**
* Type guard to check if an object is a MockList instance
* @param obj - Object to check
* @returns Type predicate for MockList
*/
function isMockList(obj: any): obj is MockList;
/**
* Recursively resolve MockList instances to arrays
* @param mockList - MockList instance to resolve
* @returns Resolved array with all nested MockLists expanded
*/
function deepResolveMockList(mockList: MockList): unknown[];Usage Examples:
// Check if value is MockList
const someValue = new MockList(5);
if (isMockList(someValue)) {
console.log('This is a MockList with items');
}
// Resolve nested MockLists
const nestedList = new MockList(2, () => new MockList(3, () => 'item'));
const resolved = deepResolveMockList(nestedList);
// resolved: [['item', 'item', 'item'], ['item', 'item', 'item']]import { MockList } from "@graphql-tools/mock";
const mockedSchema = addMocksToSchema({
schema,
mocks: {
User: () => ({
// User might have 0-5 posts
posts: () => new MockList([0, 5]),
// User has 3-10 followers
followers: () => new MockList([3, 10]),
// User always has exactly 2 contact methods
contactMethods: () => new MockList(2)
}),
BlogPost: () => ({
// Posts have 1-20 comments
comments: () => new MockList([1, 20]),
// Posts have 0-10 tags
tags: () => new MockList([0, 10], () =>
['tech', 'programming', 'tutorial', 'guide', 'tips'][Math.floor(Math.random() * 5)]
)
})
}
});// Complex custom item generation
const mockedSchema = addMocksToSchema({
schema,
mocks: {
User: () => ({
// Generate posts with realistic data
posts: () => new MockList([2, 8], () => ({
id: `post_${Math.random().toString(36).substr(2, 9)}`,
title: [
'Getting Started with GraphQL',
'Advanced Query Patterns',
'Schema Design Best Practices',
'Testing GraphQL APIs',
'Performance Optimization Tips'
][Math.floor(Math.random() * 5)],
publishedAt: new Date(
Date.now() - Math.random() * 365 * 24 * 60 * 60 * 1000
).toISOString(),
status: ['DRAFT', 'PUBLISHED', 'ARCHIVED'][Math.floor(Math.random() * 3)]
})),
// Generate activity feed
activities: () => new MockList([5, 20], () => {
const activities = [
{ type: 'POST_CREATED', description: 'Created a new post' },
{ type: 'COMMENT_ADDED', description: 'Added a comment' },
{ type: 'USER_FOLLOWED', description: 'Started following someone' }
];
const activity = activities[Math.floor(Math.random() * activities.length)];
return {
...activity,
timestamp: new Date(
Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000
).toISOString()
};
})
})
}
});// Handle nested list scenarios
const mockedSchema = addMocksToSchema({
schema,
mocks: {
Organization: () => ({
// Organization has multiple departments
departments: () => new MockList([3, 8], () => ({
name: ['Engineering', 'Marketing', 'Sales', 'HR', 'Finance'][Math.floor(Math.random() * 5)],
// Each department has multiple teams
teams: () => new MockList([1, 4], () => ({
name: ['Frontend', 'Backend', 'DevOps', 'QA'][Math.floor(Math.random() * 4)],
// Each team has multiple members
members: () => new MockList([2, 12])
}))
}))
})
}
});import { createMockStore, MockList } from "@graphql-tools/mock";
const store = createMockStore({
schema,
mocks: {
User: () => ({
// MockLists work with store references
friends: () => new MockList([5, 15], () => {
// Generate references to other users
const friendId = `user_${Math.random().toString(36).substr(2, 9)}`;
return { $ref: { typeName: 'User', key: friendId } };
}),
// Mixed content lists
notifications: () => new MockList([0, 10], () => {
const types = ['MESSAGE', 'FRIEND_REQUEST', 'POST_LIKE'];
return {
type: types[Math.floor(Math.random() * types.length)],
timestamp: new Date().toISOString(),
read: Math.random() > 0.3
};
})
})
}
});// Generate lists based on context or conditions
const mockedSchema = addMocksToSchema({
schema,
mocks: {
User: (root, args, context, info) => ({
// Admin users have more permissions
permissions: () => {
const isAdmin = Math.random() > 0.8;
return new MockList(
isAdmin ? [10, 20] : [1, 5],
() => [
'READ_POSTS', 'WRITE_POSTS', 'DELETE_POSTS',
'MANAGE_USERS', 'ADMIN_ACCESS'
][Math.floor(Math.random() * 5)]
);
},
// Premium users have more features
features: () => {
const isPremium = Math.random() > 0.7;
const baseFeatures = ['BASIC_PROFILE', 'BASIC_MESSAGING'];
const premiumFeatures = ['ADVANCED_ANALYTICS', 'PRIORITY_SUPPORT', 'CUSTOM_THEMES'];
return new MockList(
isPremium ? baseFeatures.length + premiumFeatures.length : baseFeatures.length,
() => {
const allFeatures = isPremium ? [...baseFeatures, ...premiumFeatures] : baseFeatures;
return allFeatures[Math.floor(Math.random() * allFeatures.length)];
}
);
}
})
}
});describe('List mocking tests', () => {
test('should generate variable length arrays', () => {
const mockList = new MockList([2, 5]);
const result = mockList.mock();
expect(Array.isArray(result)).toBe(true);
expect(result.length).toBeGreaterThanOrEqual(2);
expect(result.length).toBeLessThanOrEqual(5);
});
test('should use custom item generation', () => {
const mockList = new MockList(3, () => ({ type: 'test', value: 42 }));
const result = mockList.mock();
expect(result).toHaveLength(3);
result.forEach(item => {
expect(item).toMatchObject({ type: 'test', value: 42 });
});
});
test('should identify MockList instances', () => {
const mockList = new MockList(5);
const regularArray = [1, 2, 3];
expect(isMockList(mockList)).toBe(true);
expect(isMockList(regularArray)).toBe(false);
});
});