Utilities

Utilities are shared helper functions that can be used across all component types.

Export Pattern

// src/utils/index.ts
import type { Utility } from "../types";
 
export const $$Utilities: Utility[] = [
  hashGenerator,
  dataTransformer,
  formatters,
];

When to Use Utilities

Use CaseComponent Type
Validation that reports pass/failAssertion
Generating values for testsValue Generator
Modifying requests/responsesAPI Hook
Shared logic used by multiple componentsUtility

Example: Hash Generator

export const hashGenerator: Utility = {
  id: "hash-generator",
  name: "Hash Generator",
  description: "Generates various hash values",
  enabled: true,
  deprecated: false,
  tested: true,
  functions: {
    md5: (data: string) => CryptoJS.MD5(data).toString(),
    sha256: (data: string) => CryptoJS.SHA256(data).toString(),
    hmac: (data: string, key: string) => 
      CryptoJS.HmacSHA256(data, key).toString(),
    dataHash: (obj: object) => 
      CryptoJS.SHA256(JSON.stringify(obj)).toString(),
  },
};

Example: Data Transformer

export const dataTransformer: Utility = {
  id: "data-transformer",
  name: "Data Transformer",
  description: "Common data transformation functions",
  enabled: true,
  deprecated: false,
  tested: true,
  functions: {
    flatten: (obj: object, prefix = "") => {
      const result: Record<string, any> = {};
      for (const [key, value] of Object.entries(obj)) {
        const newKey = prefix ? `${prefix}.${key}` : key;
        if (typeof value === "object" && value !== null && !Array.isArray(value)) {
          Object.assign(result, dataTransformer.functions.flatten(value, newKey));
        } else {
          result[newKey] = value;
        }
      }
      return result;
    },
 
    pick: (obj: object, keys: string[]) => _.pick(obj, keys),
 
    omit: (obj: object, keys: string[]) => _.omit(obj, keys),
 
    camelToSnake: (str: string) =>
      str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`),
 
    snakeToCamel: (str: string) =>
      str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()),
  },
};

Example: Formatters

export const formatters: Utility = {
  id: "formatters",
  name: "Formatters",
  description: "String and data formatting utilities",
  enabled: true,
  deprecated: false,
  tested: true,
  functions: {
    currency: (amount: number, currency = "USD") => {
      return new Intl.NumberFormat("en-US", {
        style: "currency",
        currency,
      }).format(amount);
    },
 
    date: (timestamp: number, format = "yyyy-MM-dd") => {
      return luxon.DateTime.fromMillis(timestamp).toFormat(format);
    },
 
    phone: (number: string) => {
      const cleaned = number.replace(/\D/g, "");
      return cleaned.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3");
    },
 
    truncate: (str: string, length: number) => {
      return str.length > length ? str.slice(0, length) + "..." : str;
    },
  },
};

Using Utilities in Other Components

Utilities are available via your library’s global variable:

// In an assertion
export const hasValidHash: AssertionFunction = {
  id: "has-valid-hash",
  name: "Has Valid Hash",
  enabled: true,
  deprecated: false,
  tested: true,
  function: async (data: { content: object; hash: string }) => {
    // Use utility from same library
    const expectedHash = MyTestLib.hashGenerator.functions.dataHash(data.content);
    const passed = data.hash === expectedHash;
 
    $addAssertionResult({
      passed,
      message: passed ? "Hash is valid" : "Hash mismatch",
      operator: "hasValidHash",
      leftValue: data.hash,
      rightValue: expectedHash,
    });
  },
};
// In a value generator
export const generateFormattedOrder: ValueFunction = {
  id: "generate-formatted-order",
  name: "Generate Formatted Order",
  enabled: true,
  deprecated: false,
  tested: true,
  function: async () => {
    const order = {
      id: faker.string.uuid(),
      total: _.random(100, 1000),
      createdAt: Date.now(),
    };
 
    return {
      ...order,
      formattedTotal: MyTestLib.formatters.functions.currency(order.total),
      formattedDate: MyTestLib.formatters.functions.date(order.createdAt),
    };
  },
};

Using in Web Editor

Utilities are also available in global scripts and inline code:

// In a global script
const hash = MyTestLib.hashGenerator.functions.sha256(data);
const formatted = MyTestLib.formatters.functions.currency(amount);

Best Practices

// ✅ Good: Related functions grouped
export const dateUtils: Utility = {
  functions: {
    format: (ts, fmt) => ...,
    parse: (str, fmt) => ...,
    diff: (a, b) => ...,
  }
};
 
// ❌ Bad: Unrelated functions mixed
export const utils: Utility = {
  functions: {
    formatDate: ...,
    hashPassword: ...,
    validateEmail: ...,
  }
};

Keep Functions Pure

// ✅ Good: Pure function, no side effects
sha256: (data: string) => CryptoJS.SHA256(data).toString()
 
// ❌ Bad: Side effects
sha256: (data: string) => {
  $context.lastHash = CryptoJS.SHA256(data).toString(); // Side effect!
  return $context.lastHash;
}

Document Complex Functions

functions: {
  /**
   * Flattens a nested object into dot-notation keys
   * @example flatten({ a: { b: 1 } }) => { "a.b": 1 }
   */
  flatten: (obj: object, prefix = "") => { ... }
}