or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdlink-operations.mdtesting.mdutilities.md
tile.json

testing.mddocs/

Testing

Test utilities including mock implementations and testing helpers for validating link behavior.

Capabilities

MockLink Class

Mock implementation of ApolloLink for testing purposes that allows custom request handling.

/**
 * Mock implementation of ApolloLink for testing
 */
class MockLink extends ApolloLink {
  /**
   * Creates a new MockLink with optional request handler
   * @param handleRequest - Optional request handler function (defaults to returning null)
   */
  constructor(handleRequest?: RequestHandler);

  /**
   * Processes GraphQL operation (should be overridden in constructor)
   * @param operation - GraphQL operation
   * @param forward - Forward function (for non-terminating mocks)
   * @returns Observable or null
   */
  request(operation: Operation, forward?: NextLink): Observable<FetchResult> | null;
}

Usage Examples:

import { MockLink, Observable } from "apollo-link";

// Mock link that returns predefined data
const mockLink = new MockLink((operation) => {
  return new Observable(observer => {
    if (operation.operationName === "GetUser") {
      observer.next({
        data: { user: { id: "123", name: "John Doe" } }
      });
      observer.complete();
    } else {
      observer.error(new Error("Unknown operation"));
    }
  });
});

// Mock link that simulates errors
const errorMockLink = new MockLink(() => {
  return new Observable(observer => {
    observer.error(new Error("Network error"));
  });
});

// Mock link for testing forwarding behavior
const forwardingMockLink = new MockLink((operation, forward) => {
  // Modify operation and forward
  operation.setContext({ timestamp: Date.now() });
  return forward ? forward(operation) : Observable.of();
});

SetContextLink Class

Link that modifies the operation context using a provided function, useful for testing context manipulation.

/**
 * Link that modifies operation context for testing
 */
class SetContextLink extends ApolloLink {
  /**
   * Creates a link that modifies operation context
   * @param setContext - Function to modify context (defaults to identity function)
   */
  constructor(setContext?: (context: Record<string, any>) => Record<string, any>);

  /**
   * Modifies operation context and forwards to next link
   * @param operation - GraphQL operation
   * @param forward - Forward function to next link
   * @returns Observable from forwarded operation
   */
  request(operation: Operation, forward: NextLink): Observable<FetchResult>;
}

Usage Examples:

import { SetContextLink, from } from "apollo-link";

// Add authentication headers
const authContextLink = new SetContextLink((context) => ({
  ...context,
  headers: {
    ...context.headers,
    Authorization: "Bearer test-token"
  }
}));

// Add request timestamp
const timestampLink = new SetContextLink((context) => ({
  ...context,
  requestTime: Date.now()
}));

// Chain with other links
const link = from([authContextLink, timestampLink, httpLink]);

Testing Utilities

testLinkResults Function

Executes a link with a GraphQL operation and validates the results against expected outcomes.

/**
 * Executes a link and validates results against expected outcomes
 * @param params - Test configuration object
 */
function testLinkResults(params: TestResultType): void;

interface TestResultType {
  /** Link to test */
  link: ApolloLink;
  /** Expected results array (optional) */
  results?: any[];
  /** GraphQL query string or AST (optional, uses default if not provided) */
  query?: string;
  /** Callback to invoke when test completes (optional) */
  done?: () => void;
  /** Context to pass with operation (optional) */
  context?: any;
  /** Variables to pass with operation (optional) */
  variables?: any;
}

Usage Examples:

import { testLinkResults, MockLink } from "apollo-link";
import gql from "graphql-tag";

// Test successful response
const successLink = new MockLink(() => 
  Observable.of({ data: { user: { id: "123" } } })
);

testLinkResults({
  link: successLink,
  results: [{ user: { id: "123" } }],
  query: gql`query { user { id } }`,
  done: () => console.log("Test completed")
});

// Test error handling
const errorLink = new MockLink(() => 
  Observable.throw(new Error("Test error"))
);

testLinkResults({
  link: errorLink,
  results: [new Error("Test error")], // Errors go at the end of results array
  done: () => console.log("Error test completed")
});

// Test with context and variables
testLinkResults({
  link: contextAwareLink,
  results: [{ data: { posts: [] } }],
  context: { userId: "123" },
  variables: { limit: 10 },
  query: gql`query GetPosts($limit: Int!) { posts { id title } }`
});

checkCalls Function

Helper function for checking function call results in tests, typically used internally by testLinkResults.

/**
 * Helper for checking function call results in tests
 * @param calls - Array of function calls (typically jest.fn().mock.calls)
 * @param results - Expected results array
 */
function checkCalls<T>(calls: any[], results: Array<T>): void;

Usage Example:

import { checkCalls } from "apollo-link";

// Typically used with Jest mocks
const mockFn = jest.fn();

// Simulate some calls
mockFn({ data: { user: "John" } });
mockFn({ data: { user: "Jane" } });

// Check that calls match expected results
checkCalls(mockFn.mock.calls, [
  { user: "John" },
  { user: "Jane" }
]);

Testing Patterns

Testing Link Composition

import { from, split, MockLink, testLinkResults } from "apollo-link";

describe("Link composition", () => {
  it("should chain links correctly", () => {
    const authLink = new MockLink((op, forward) => {
      op.setContext({ auth: "token" });
      return forward(op);
    });

    const httpLink = new MockLink((op) => {
      const context = op.getContext();
      expect(context.auth).toBe("token");
      return Observable.of({ data: { success: true } });
    });

    const link = from([authLink, httpLink]);

    testLinkResults({
      link,
      results: [{ success: true }],
      done: () => console.log("Composition test passed")
    });
  });
});

Testing Conditional Routing

import { split, MockLink } from "apollo-link";

const httpLink = new MockLink(() => 
  Observable.of({ data: { query: "http" } })
);

const wsLink = new MockLink(() => 
  Observable.of({ data: { subscription: "ws" } })
);

const link = split(
  ({ query }) => query.definitions[0].operation === "subscription",
  wsLink,
  httpLink
);

// Test subscription routing
testLinkResults({
  link,
  query: gql`subscription { messageAdded { id } }`,
  results: [{ subscription: "ws" }]
});

// Test query routing  
testLinkResults({
  link,
  query: gql`query { users { id } }`,
  results: [{ query: "http" }]
});

Testing Error Scenarios

import { MockLink, fromError } from "apollo-link";

const networkErrorLink = new MockLink(() => 
  fromError(new Error("Network timeout"))
);

const graphqlErrorLink = new MockLink(() => 
  Observable.of({
    errors: [{ message: "User not found" }],
    data: null
  })
);

// Test network errors
testLinkResults({
  link: networkErrorLink,
  results: [new Error("Network timeout")]
});

// Test GraphQL errors  
testLinkResults({
  link: graphqlErrorLink,
  results: [{
    errors: [{ message: "User not found" }],
    data: null
  }]
});