Value Generators

Value generators create dynamic test data that QA can use in visual test flows.

Export Pattern

// src/generators/index.ts
import type { ValueFunction } from "../types";
 
export const $$ValueFunctions: ValueFunction[] = [
  generateUserId,
  generateTestUser,
  generateOrder,
];

Function Signature

Generators accept 0 or 1 parameter:

// No parameters
async function generateTimestamp()
 
// Single parameter (object for flexibility)
async function generateTestUser(options?: { role?: string; verified?: boolean })

Example: Simple Generator

export const generateUserId: ValueFunction = {
  id: "generate-user-id",
  name: "Generate User ID",
  description: "Creates a unique user identifier",
  enabled: true,
  deprecated: false,
  tested: true,
  function: async () => {
    return `user_${Date.now()}_${_.random(1000, 9999)}`;
  },
};

Example: Parameterized Generator

import { z } from "zod";
 
const TestUserSchema = z.object({
  role: z.enum(["admin", "user", "guest"]).default("user"),
  verified: z.boolean().default(false),
  count: z.number().int().positive().default(1),
});
 
export const generateTestUsers: ValueFunction = {
  id: "generate-test-users",
  name: "Generate Test Users",
  description: "Creates test user objects with configurable options",
  enabled: true,
  deprecated: false,
  tested: true,
  function: async (options?: unknown) => {
    const config = TestUserSchema.parse(options || {});
 
    const users = [];
    for (let i = 0; i < config.count; i++) {
      users.push({
        id: faker.number.int({ min: 1000, max: 9999 }),
        email: faker.internet.email(),
        name: faker.person.fullName(),
        role: config.role,
        verified: config.verified,
        createdAt: Date.now(),
      });
    }
 
    return config.count === 1 ? users[0] : users;
  },
};

Example: Using Context

export const generateOrderForUser: ValueFunction = {
  id: "generate-order-for-user",
  name: "Generate Order for User",
  description: "Creates an order linked to the current user in context",
  enabled: true,
  deprecated: false,
  tested: true,
  function: async (options?: { itemCount?: number }) => {
    const itemCount = options?.itemCount || 3;
    const userId = $context.userId; // Read from test context
 
    const items = [];
    let total = 0;
 
    for (let i = 0; i < itemCount; i++) {
      const price = _.random(10, 200);
      const quantity = _.random(1, 5);
      items.push({
        id: faker.string.uuid(),
        name: faker.commerce.productName(),
        price,
        quantity,
      });
      total += price * quantity;
    }
 
    return {
      id: faker.string.uuid(),
      userId,
      items,
      total,
      currency: "USD",
      createdAt: Date.now(),
    };
  },
};

Example: Fetching Remote Data

export const fetchTestUser: ValueFunction = {
  id: "fetch-test-user",
  name: "Fetch Test User",
  description: "Retrieves a test user from the test data API",
  enabled: true,
  deprecated: false,
  tested: true,
  function: async (criteria?: { role?: string }) => {
    const baseUrl = $vars.testDataApiUrl || "https://test-data.example.com";
    const params = new URLSearchParams();
    
    if (criteria?.role) {
      params.append("role", criteria.role);
    }
 
    const response = await ky.get(`${baseUrl}/users?${params}`).json();
    return response.data;
  },
};

Parameter Validation

Always validate parameters with Zod:

const OptionsSchema = z.object({
  count: z.number().int().positive().default(10),
  type: z.enum(["user", "admin"]).default("user"),
}).default({});
 
function: async (options?: unknown) => {
  const config = OptionsSchema.parse(options);
  // Use validated config
}

Best Practices

Use Object Parameters

// ✅ Good: Flexible, extensible
function: async (options?: { count?: number; type?: string })
 
// ❌ Bad: Hard to extend
function: async (count: number, type: string, verified: boolean)

Provide Defaults

const config = OptionsSchema.parse(options || {});
// If options is undefined, defaults are applied

Use Descriptive Names

// ✅ Good
id: "generate-authenticated-user-with-permissions"
 
// ❌ Bad
id: "gen-user"

Usage in Tests

Once synced and enabled:

  • Context Operations → Select from dropdown
  • Script Nodeconst user = await $gen.generateTestUser({ role: "admin" })
  • JS Expressionjs: $gen.generateUserId()