Traditional element selectors are fragile. A single DOM change can break dozens of tests. wdio-ai-locator-service takes a radically different approach — describe what you want in plain English, and let AI find it for you.

The Problem with Traditional Selectors

FeatureTraditional SelectorsAI Locator Service
MaintainabilityManual updates neededSelf-healing locators
ReadabilityComplex XPath/CSSPlain English
SpeedWrite & debug selectorsDescribe what you want
ResilienceBreaks on DOM changesAdapts automatically
CollaborationTechnical knowledge requiredAnyone can write tests

Features

  • Natural Language — Find elements using plain English descriptions
  • Self-Healing — Auto-regenerates locators when UI changes
  • Smart Caching — Reduces AI calls by 99% with intelligent caching
  • Template Variables — Reusable dynamic locators with {variable} syntax
  • Multi-Provider Support — Works with OpenAI, OpenAI Router, and Ollama
  • Usage Tracking — Monitor AI API consumption and costs
  • Auto-Retry — Multiple fallback strategies for maximum reliability

Installation

npm install wdio-ai-locator-service --save-dev

Quick Start

Step 1: Configure the Service

// wdio.conf.ts
export const config = {
  services: [
    ['ai-locator', {
      provider: 'openai',
      apiKey: process.env.OPENAI_API_KEY,
      model: 'gpt-4o-mini',
      enableUsageTracking: true,
      cachePath: './.ai-locator-cache.json'
    }]
  ]
}

Step 2: Write Tests with Natural Language

describe('Login Flow', () => {
  it('should login successfully', async () => {
    await browser.url('https://example.com/login')

    const emailInput = await browser.aiLocator('email input field')
    await $(emailInput).setValue('user@example.com')

    const passwordInput = await browser.aiLocator('password field')
    await $(passwordInput).setValue('secret123')

    const loginButton = await browser.aiLocator('login button')
    await $(loginButton).click()
  })
})

Template Variables for Data-Driven Testing

The killer feature — use template caching to make 1 AI call instead of N calls in loops:

const users = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve']

for (const userName of users) {
  const locator = await browser.aiLocator('Edit button for {userName}', {
    variables: { userName },
    cacheBy: 'template'  // Only 1 AI call for all 5 users!
  })
  await $(locator).click()
}
// Without template caching: 5 AI calls
// With template caching: 1 AI call — 80% cost reduction!

Global Context

Set variables once, use everywhere:

describe('User Management', () => {
  beforeEach(async () => {
    await browser.setAiContext({
      userName: 'John Doe',
      role: 'admin'
    })
  })

  afterEach(async () => {
    await browser.clearAiContext()
  })

  it('should manage profile', async () => {
    const profileLoc = await browser.aiLocator('Profile for {userName}')
    await $(profileLoc).click()
  })
})

Multi-Provider Support

ProviderCostSpeedAccuracyPrivacy
OpenAI$$FastExcellentCloud
OpenAI Router$GoodGoodCloud
OllamaFreeGoodGoodLocal

Ollama (Local / Free)

services: [
  ['ai-locator', {
    provider: 'ollama',
    model: 'llama3',
    baseUrl: 'http://localhost:11434'
  }]
]

Auto-Heal Feature

When a cached locator fails to find an element, the service automatically:

  1. Detects that the cached selector no longer works
  2. Sends a fresh request to the AI with the current page DOM
  3. Generates new selectors and updates the cache
  4. Continues the test without manual intervention

For the full documentation, visit the GitHub repo.


Want to try AI-powered testing? Feel free to reach out or open an issue on GitHub.