> ## Documentation Index
> Fetch the complete documentation index at: https://docs.browsertest.in/llms.txt
> Use this file to discover all available pages before exploring further.

# TemplateAPI

> Methods for managing and executing test templates

## Overview

The `TemplateAPI` provides methods for creating, managing, and executing reusable test templates with structured output schemas.

## Methods

### create()

Creates a new test template.

```typescript theme={null}
create(options: TemplateOptions): Promise<TemplateResponse>
```

#### Parameters

| Parameter | Type              | Required | Description                    |
| --------- | ----------------- | -------- | ------------------------------ |
| `options` | `TemplateOptions` | Yes      | Template configuration options |

#### TemplateOptions

```typescript theme={null}
interface TemplateOptions {
  /** Template name */
  name: string;
  /** Template description */
  description: string;
  /** Test instructions */
  instructions: string;
  /** JSON schema for structured output */
  outputSchema: object;
  /** Template tags for organization */
  tags?: string[];
}
```

#### Returns

`Promise<TemplateResponse>` - Template creation response

#### TemplateResponse

```typescript theme={null}
interface TemplateResponse {
  template: {
    id: string;
    name: string;
    description: string;
    instructions: string;
    outputSchema: object;
    tags: string[];
    createdAt: string;
    updatedAt: string;
  };
}
```

#### Example

```javascript theme={null}
const template = await bt.template.create({
  name: 'E-commerce Checkout Test',
  description: 'Test the complete checkout flow',
  instructions: `
    Navigate to the product page.
    Add item to cart.
    Proceed to checkout.
    Fill in shipping information.
    Complete payment.
    Verify order confirmation.
  `,
  outputSchema: {
    type: 'object',
    properties: {
      checkoutSuccessful: { type: 'boolean' },
      orderNumber: { type: 'string' },
      totalAmount: { type: 'string' },
      errors: { type: 'array', items: { type: 'string' } }
    }
  },
  tags: ['checkout', 'e-commerce', 'payment']
});

console.log('Template created:', template.template.id);
```

### invoke()

Invokes a template to create an async test job.

```typescript theme={null}
invoke(templateId: string, options: TemplateInvocationOptions): Promise<TemplateJobResponse>
```

#### Parameters

| Parameter    | Type                        | Required | Description                  |
| ------------ | --------------------------- | -------- | ---------------------------- |
| `templateId` | `string`                    | Yes      | ID of the template to invoke |
| `options`    | `TemplateInvocationOptions` | Yes      | Invocation options           |

#### TemplateInvocationOptions

```typescript theme={null}
interface TemplateInvocationOptions {
  /** URL to test */
  url: string;
  /** Test configuration overrides */
  config?: TestConfig;
  /** Parameter values for template variables */
  parameters?: Record<string, any>;
}
```

#### Returns

`Promise<TemplateJobResponse>` - Job creation response

#### TemplateJobResponse

```typescript theme={null}
interface TemplateJobResponse {
  jobId: string;
  status: 'pending' | 'running' | 'completed' | 'failed';
  createdAt: string;
  url: string;
}
```

#### Example

```javascript theme={null}
const job = await bt.template.invoke(template.template.id, {
  url: 'https://example-shop.com/checkout',
  config: {
    viewport: { width: 1920, height: 1080 },
    waitFor: 3000,
    timeout: 120000
  },
  parameters: {
    productId: '12345',
    quantity: 2
  }
});

console.log('Job created:', job.jobId);
```

### createAndInvoke()

Creates a template and immediately invokes it.

```typescript theme={null}
createAndInvoke(options: TemplateOptions & TemplateInvocationOptions): Promise<TemplateJobResponse>
```

#### Parameters

| Parameter | Type                                          | Required | Description                              |
| --------- | --------------------------------------------- | -------- | ---------------------------------------- |
| `options` | `TemplateOptions & TemplateInvocationOptions` | Yes      | Combined template and invocation options |

#### Returns

`Promise<TemplateJobResponse>` - Job creation response

#### Example

```javascript theme={null}
const result = await bt.template.createAndInvoke({
  name: 'Quick Page Check',
  instructions: 'Navigate to page and verify it loads without errors',
  url: 'https://example.com',
  outputSchema: {
    type: 'object',
    properties: {
      pageLoaded: { type: 'boolean' },
      hasErrors: { type: 'boolean' },
      loadTime: { type: 'number' }
    }
  }
});

console.log('Template created and invoked:', result.jobId);
```

### list()

Lists templates with optional filtering.

```typescript theme={null}
list(options?: TemplateListOptions): Promise<TemplateListResponse>
```

#### Parameters

| Parameter | Type                  | Required | Description                      |
| --------- | --------------------- | -------- | -------------------------------- |
| `options` | `TemplateListOptions` | No       | Filtering and pagination options |

#### TemplateListOptions

```typescript theme={null}
interface TemplateListOptions {
  /** Search query for template names */
  search?: string;
  /** Filter by tags */
  tags?: string[];
  /** Maximum number of results */
  limit?: number;
  /** Number of results to skip */
  offset?: number;
  /** Sort order */
  sortOrder?: 'asc' | 'desc';
}
```

#### Returns

`Promise<TemplateListResponse>` - List of templates

#### TemplateListResponse

```typescript theme={null}
interface TemplateListResponse {
  templates: Array<{
    id: string;
    name: string;
    description: string;
    tags: string[];
    createdAt: string;
    updatedAt: string;
  }>;
  total: number;
  hasMore: boolean;
}
```

#### Examples

```javascript theme={null}
// Get all templates
const allTemplates = await bt.template.list();

// Search by name
const searchResults = await bt.template.list({
  search: 'checkout'
});

// Filter by tags
const taggedTemplates = await bt.template.list({
  tags: ['e-commerce', 'payment']
});

// Paginated results
const page1 = await bt.template.list({ limit: 10, offset: 0 });
const page2 = await bt.template.list({ limit: 10, offset: 10 });
```

### update()

Updates an existing template.

```typescript theme={null}
update(templateId: string, updates: Partial<TemplateOptions>): Promise<TemplateResponse>
```

#### Parameters

| Parameter    | Type                       | Required | Description                  |
| ------------ | -------------------------- | -------- | ---------------------------- |
| `templateId` | `string`                   | Yes      | ID of the template to update |
| `updates`    | `Partial<TemplateOptions>` | Yes      | Fields to update             |

#### Returns

`Promise<TemplateResponse>` - Updated template response

#### Example

```javascript theme={null}
const updated = await bt.template.update(template.template.id, {
  name: 'Updated Checkout Test',
  description: 'Improved checkout testing template',
  tags: ['checkout', 'e-commerce', 'payment', 'updated']
});

console.log('Template updated:', updated.template.name);
```

### delete()

Deletes a template.

```typescript theme={null}
delete(templateId: string): Promise<void>
```

#### Parameters

| Parameter    | Type     | Required | Description                  |
| ------------ | -------- | -------- | ---------------------------- |
| `templateId` | `string` | Yes      | ID of the template to delete |

#### Returns

`Promise<void>` - Resolves when template is deleted

#### Example

```javascript theme={null}
await bt.template.delete(template.template.id);
console.log('Template deleted');
```

## Advanced Usage

### Parameterized Templates

```typescript theme={null}
const parameterizedTemplate = await bt.template.create({
  name: 'Custom Form Test',
  instructions: `
    Navigate to {{formUrl}}
    Fill out the form with:
    - Name: {{userName}}
    - Email: {{userEmail}}
    - Message: {{userMessage}}
    Submit the form
    Verify success message: "{{expectedMessage}}"
  `,
  outputSchema: {
    type: 'object',
    properties: {
      formSubmitted: { type: 'boolean' },
      successMessage: { type: 'string' },
      formValid: { type: 'boolean' }
    }
  }
});

// Invoke with parameters
const job = await bt.template.invoke(parameterizedTemplate.template.id, {
  url: 'https://example.com',
  parameters: {
    formUrl: '/contact',
    userName: 'John Doe',
    userEmail: 'john@example.com',
    userMessage: 'Test message',
    expectedMessage: 'Thank you for your message!'
  }
});
```

### Template Versioning

```typescript theme={null}
class TemplateManager {
  constructor(private bt: BrowserTest) {}

  async createVersion(templateId: string, updates: Partial<TemplateOptions>): Promise<string> {
    // Get current template
    const current = await this.getTemplateById(templateId);

    // Create new version
    const versionedName = `${current.name} v${Date.now()}`;
    const newTemplate = await this.bt.template.create({
      ...current,
      name: versionedName,
      ...updates
    });

    return newTemplate.template.id;
  }

  async getTemplateById(templateId: string): Promise<TemplateOptions> {
    // This would require a get method (not currently available)
    // For now, we'll need to track templates in our application
    throw new Error('Template retrieval not implemented in SDK');
  }

  async archiveTemplate(templateId: string): Promise<void> {
    await this.bt.template.update(templateId, {
      tags: ['archived', 'deprecated']
    });
  }
}
```

### Template Categories

```typescript theme={null}
class TemplateOrganizer {
  constructor(private bt: BrowserTest) {}

  async createCategorizedTemplate(
    category: string,
    options: TemplateOptions
  ): Promise<TemplateResponse> {
    const categorizedOptions = {
      ...options,
      tags: [...(options.tags || []), `category:${category}`]
    };

    return this.bt.template.create(categorizedOptions);
  }

  async getTemplatesByCategory(category: string): Promise<TemplateListResponse> {
    return this.bt.template.list({
      tags: [`category:${category}`]
    });
  }

  async getAllCategories(): Promise<string[]> {
    const allTemplates = await this.bt.template.list({ limit: 1000 });
    const categories = new Set<string>();

    allTemplates.templates.forEach(template => {
      template.tags.forEach(tag => {
        if (tag.startsWith('category:')) {
          categories.add(tag.replace('category:', ''));
        }
      });
    });

    return Array.from(categories);
  }
}

// Usage
const organizer = new TemplateOrganizer(bt);

await organizer.createCategorizedTemplate('ecommerce', {
  name: 'Product Search Test',
  description: 'Test product search functionality',
  instructions: 'Test search functionality...',
  outputSchema: { /* schema */ },
  tags: ['search', 'products']
});

const ecommerceTemplates = await organizer.getTemplatesByCategory('ecommerce');
const categories = await organizer.getAllCategories();
```

## Error Handling

### Template Creation Errors

```javascript theme={null}
try {
  const template = await bt.template.create({
    name: 'Test Template',
    description: 'A test template',
    instructions: 'Test instructions',
    outputSchema: { type: 'object', properties: {} }
  });
} catch (error) {
  if (error.name === 'BrowserTestAPIError') {
    console.log('Template creation failed:', error.message);
  }
}
```

### Template Invocation Errors

```javascript theme={null}
try {
  const job = await bt.template.invoke(templateId, {
    url: 'https://example.com'
  });
} catch (error) {
  if (error.name === 'BrowserTestAuthError') {
    console.log('Authentication failed - check API key');
  } else if (error.name === 'BrowserTestQuotaError') {
    console.log('Quota exceeded for template invocation');
  }
}
```

## Best Practices

### Template Design

1. **Clear naming**: Use descriptive names that indicate the template's purpose
2. **Comprehensive instructions**: Include all necessary steps and edge cases
3. **Structured output**: Define clear schemas for consistent results
4. **Appropriate tags**: Use tags for categorization and filtering
5. **Parameterization**: Use variables for flexible templates

### Organization

```javascript theme={null}
// Template naming convention
const namingConvention = {
  prefix: {
    'ui': 'User Interface',
    'api': 'API Integration',
    'e2e': 'End-to-End',
    'perf': 'Performance'
  },
  pattern: '{Prefix} - {Feature} - {Action}'
};

// Example: "UI - Login - Authentication Flow"
```

### Maintenance

```javascript theme={null}
class TemplateMaintainer {
  constructor(private bt: BrowserTest) {}

  async validateTemplate(templateId: string): Promise<boolean> {
    try {
      // Try to invoke template with test data
      const testJob = await this.bt.template.invoke(templateId, {
        url: 'https://httpbin.org/html', // Simple test page
        config: { timeout: 30000 }
      });

      // Wait for completion
      const status = await this.waitForJob(testJob.jobId, 60000);
      return status === 'completed';

    } catch (error) {
      console.error(`Template ${templateId} validation failed:`, error.message);
      return false;
    }
  }

  private async waitForJob(jobId: string, timeout: number): Promise<string> {
    const startTime = Date.now();

    while (Date.now() - startTime < timeout) {
      const status = await this.bt.testing.getStatus(jobId);

      if (status.job.status === 'completed' || status.job.status === 'failed') {
        return status.job.status;
      }

      await new Promise(resolve => setTimeout(resolve, 2000));
    }

    throw new Error('Job timeout');
  }

  async cleanupOldTemplates(daysOld: number = 90): Promise<number> {
    const cutoff = new Date();
    cutoff.setDate(cutoff.getDate() - daysOld);

    // Note: This would require additional API methods not currently available
    // For now, this is a conceptual implementation
    console.log(`Would clean up templates older than ${cutoff.toISOString()}`);
    return 0;
  }
}
```

### Performance Considerations

```javascript theme={null}
// Cache frequently used templates
class TemplateCache {
  private cache = new Map<string, TemplateResponse>();
  private readonly ttl = 5 * 60 * 1000; // 5 minutes

  constructor(private bt: BrowserTest) {}

  async get(templateId: string): Promise<TemplateResponse | null> {
    const cached = this.cache.get(templateId);

    if (cached && Date.now() - cached.timestamp < this.ttl) {
      return cached.data;
    }

    // Cache miss - fetch from API
    try {
      // Note: Template retrieval not currently available in SDK
      // This would require additional API methods
      return null;
    } catch (error) {
      console.error('Failed to fetch template:', error.message);
      return null;
    }
  }

  set(templateId: string, data: TemplateResponse): void {
    this.cache.set(templateId, {
      data,
      timestamp: Date.now()
    });
  }

  clear(): void {
    this.cache.clear();
  }
}
```
