Testdriver:Locating Elements logo

Testdriver:Locating Elements

Organization
testdriverai
testdriver:locating-elements

Locate UI elements using AI

Overview

Publishertestdriverai
Repositorytestdriverai
Skill nametestdriver:locating-elements
Stars
465
Forks
39
Bundled files
Instructions only
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by testdriverai on GitHub. Read the source before you install it.

Installation

Install the Testdriver:Locating Elements AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/testdriverai/testdriverai/tree/main/ai/skills/testdriver-locating-elements
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/testdriverai/testdriverai.git /tmp/testdriverai
mkdir -p .claude/skills
cp -r /tmp/testdriverai/ai/skills/testdriver-locating-elements .claude/skills/testdriverai-testdriver-locating-elements
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Testdriver:Locating Elements in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Testdriver:Locating Elements on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Testdriver:Locating Elements is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Overview

The TestDriver element finding system uses AI. It finds elements on the screen with natural language descriptions. The find() method returns an Element object. You can interact with the object.

Finding Elements

find()

Find an element on the screen with a natural language description.

javascript
const element = await testdriver.find(description)

Parameters:

  • description (string) - A natural language description of the element to find

Returns: Promise<Element> - The Element instance that TestDriver found

Example:

javascript
// Find a button
const submitButton = await testdriver.find('the submit button');

// Find an input field with context
const emailField = await testdriver.find('email input field in the login form');

// Find an element by visual characteristics
const redButton = await testdriver.find('red button in the top right corner');

Element Class

The Element class represents a located (or to-be-located) UI element. It provides methods for interaction and properties for element information. For interaction methods like click() and hover(), see Interacting With Your App.

Methods

found()

Check if the element was successfully located.

javascript
element.found()

Returns: boolean - True if element coordinates were found

Example:

javascript
const element = await testdriver.find('login button');
if (element.found()) {
  await element.click();
} else {
  console.log('Element not found');
}
find()

Re-locate the element, optionally with a new description.

javascript
await element.find(newDescription)

Parameters:

  • newDescription (string, optional) - New description to search for

Returns: Promise<Element> - This element instance

Example:

javascript
// Re-locate if the UI changed
const element = await testdriver.find('submit button');
// ... page updates ...
await element.find(); // Re-locate with same description

// Or update the description
await element.find('blue submit button'); // Now looking for blue button

Properties

Element properties provide additional information about located elements. Properties are available after a successful find() call.

coordinates

Get the element's coordinates object containing all position information.

javascript
const coords = element.getCoordinates()
// or access directly
element.coordinates

Returns: Object | null - Coordinate object with { x, y, centerX, centerY }

Example:

javascript
const button = await testdriver.find('submit button');
const coords = button.coordinates;

if (coords) {
  console.log(`Top-left: (${coords.x}, ${coords.y})`);
  console.log(`Center: (${coords.centerX}, ${coords.centerY})`);
}
x, y, centerX, centerY

Direct access to coordinate values. Always available after successful find().

javascript
element.x        // Top-left X coordinate (number)
element.y        // Top-left Y coordinate (number)
element.centerX  // Center X coordinate (number)
element.centerY  // Center Y coordinate (number)

Example:

javascript
const button = await testdriver.find('submit button');
console.log(`Button at: (${button.x}, ${button.y})`);
console.log(`Button center: (${button.centerX}, ${button.centerY})`);

// Use for custom mouse operations
await testdriver.click(button.centerX, button.centerY);
width, height

Element dimensions in pixels. Available when AI detects element bounds.

javascript
element.width   // Width in pixels (number | null)
element.height  // Height in pixels (number | null)

Example:

javascript
const button = await testdriver.find('submit button');

if (button.width && button.height) {
  console.log(`Button size: ${button.width}x${button.height}px`);
  
  // Check if button is large enough
  if (button.width < 50) {
    console.warn('Button might be too small');
  }
}
boundingBox

Complete bounding box information including position and dimensions.

javascript
element.boundingBox

Returns: Object | null - Bounding box with all dimension data

typescript
{
  x: number,        // Top-left X
  y: number,        // Top-left Y
  width: number,    // Width in pixels
  height: number    // Height in pixels
}

Example:

javascript
const element = await testdriver.find('dialog box');

if (element.boundingBox) {
  const { x, y, width, height } = element.boundingBox;
  console.log(`Dialog: ${width}x${height} at (${x}, ${y})`);
  
  // Calculate if element is in viewport
  const rightEdge = x + width;
  const bottomEdge = y + height;
  console.log(`Element extends to (${rightEdge}, ${bottomEdge})`);
}
screenshot

Base64-encoded PNG screenshot of the screen when element was found. Only available in DEBUG mode or when an error occurs.

javascript
element.screenshot

Returns: string | null - Base64-encoded PNG image

Example:

javascript
const element = await testdriver.find('error message');

if (element.screenshot) {
  // Save screenshot to file
  const fs = require('fs');
  const base64Data = element.screenshot.replace(/^data:image\/\w+;base64,/, '');
  fs.writeFileSync('element-screenshot.png', Buffer.from(base64Data, 'base64'));
  console.log('Screenshot saved');
}
text

Text content extracted from the element by AI (if available).

javascript
element.text

Returns: string | null - Element's text content

Example:

javascript
const message = await testdriver.find('notification message');

if (message.text) {
  console.log('Message says:', message.text);
  
  // Use text content in assertions
  if (message.text.includes('success')) {
    console.log('Success message detected');
  }
}

// Another example - extracting button label
const button = await testdriver.find('blue button');
console.log('Button text:', button.text); // "Submit"
label

Accessible label or name of the element (if available). Useful for verifying accessibility.

javascript
element.label

Returns: string | null - Accessible label

Example:

javascript
const input = await testdriver.find('first input field');

if (input.label) {
  console.log('Input label:', input.label); // "Email Address"
}
confidence

AI confidence score for the element match (0-1, where 1 is perfect confidence).

javascript
element.confidence

Returns: number | null - Confidence score between 0 and 1

Example:

javascript
const element = await testdriver.find('submit button');

if (element.confidence !== null) {
  const percentage = (element.confidence * 100).toFixed(1);
  console.log(`Match confidence: ${percentage}%`);
  
  if (element.confidence < 0.8) {
    console.warn('⚠️ Low confidence match - element might not be correct');
  } else if (element.confidence > 0.95) {
    console.log('✅ High confidence match');
  }
}

Property Availability

PropertyWhen Available
x, y, centerX, centerY✅ Always after successful find()
coordinates✅ Always after successful find()
width, height⚠️ When AI detects element bounds
boundingBox⚠️ When AI detects element bounds
text⚠️ When AI extracts text content
label⚠️ When element has accessible label
confidence✅ Always after AI element finding
screenshot⚠️ Only in DEBUG mode or on errors

JSON Serialization

Element objects can be safely serialized using JSON.stringify() for logging, debugging, and data storage. Circular references are automatically removed:

javascript
const element = await testdriver.find('login button');

// Safe to stringify - no circular reference errors!
console.log(JSON.stringify(element, null, 2));

Serialized output includes:

json
{
  "description": "login button",
  "coordinates": { "x": 100, "y": 200, "centerX": 150, "centerY": 225 },
  "found": true,
  "threshold": 0.01,
  "x": 100,
  "y": 200,
  "cache": {
    "hit": true,
    "strategy": "pixel-diff",
    "createdAt": "2025-12-09T10:30:00.000Z",
    "diffPercent": 0.0023,
    "imageUrl": "https://cache.testdriver.ai/..."
  },
  "similarity": 0.98,
  "confidence": 0.95,
  "selector": "button#login",
  "aiResponse": "Found the blue login button in the center of the form..."
}

Serialized properties:

PropertyTypeDescription
descriptionstringElement search description
coordinatesobjectFull coordinate object {x, y, centerX, centerY}
foundbooleanWhether element was located
thresholdnumberCache threshold used for this find
x, ynumberTop-left coordinates
cache.hitbooleanWhether cache was used
cache.strategystringCache strategy (e.g., "pixel-diff")
cache.createdAtstringISO timestamp when cache was created
cache.diffPercentnumberPixel difference from cached image
cache.imageUrlstringURL to cached screenshot
similaritynumberSimilarity score (0-1)
confidencenumberAI confidence score (0-1)
selectorstringCSS/XPath selector if available
aiResponsestringAI's explanation of what it found

Use cases:

javascript
// Debugging element detection
const element = await testdriver.find('submit button');
if (!element.found()) {
  console.error('Element not found:', JSON.stringify(element, null, 2));
}

// Logging cache performance
const data = JSON.parse(JSON.stringify(element));
if (data.cache.hit) {
  console.log(`Cache hit! Diff: ${(data.cache.diffPercent * 100).toFixed(2)}%`);
}

// Sharing element data across processes
const elementData = JSON.stringify(element);
// Send to another process, log to file, etc.

Best Practices

```javascript
// ❌ Too vague
await testdriver.find('button');

// ✅ Specific
await testdriver.find('blue submit button below the email field');
```
```javascript
const element = await testdriver.find('submit button');
if (!element.found()) {
  throw new Error('Submit button not found');
}
await element.click();
```

Frequently asked questions

What does the Testdriver:Locating Elements AI skill do?

Locate UI elements using AI

Why use Testdriver:Locating Elements on TypingMind?

Because you install it once and use it with any model. Testdriver:Locating Elements is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Testdriver:Locating Elements in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/testdriverai/testdriverai/tree/main/ai/skills/testdriver-locating-elements. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Testdriver:Locating Elements?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Testdriver:Locating Elements?

As many as you like. As long as a model supports skills, you can use Testdriver:Locating Elements with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Testdriver:Locating Elements AI skill free?

It is published on GitHub by testdriverai. Check the repository for licensing terms. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇