You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过selenium-webdriver.Builder创建浏览器时,如何正确定义Protractor的$?

Fixing "$ is undefined" or "$ is not a function" When Using Protractor's $ with Selenium WebDriver Builder

Hey there! Let's break down why you're hitting this issue and how to get Protractor's handy $ selector working smoothly with your Selenium WebDriver setup.

Why This Happens

Protractor's $ and $$ are custom wrapper functions built on top of Selenium WebDriver—they’re designed to work within Protractor’s test framework environment. When you directly use require('selenium-webdriver').Builder to spin up a browser instance, you’re operating in a raw Selenium context. Protractor’s global utilities like $ aren’t automatically loaded or linked to your driver, which is why you see those "undefined" or "not a function" errors.


If you want to keep using Protractor’s $, you need to explicitly bind your Selenium driver to Protractor’s browser object. Here’s a step-by-step implementation:

const { Builder } = require('selenium-webdriver');
const protractor = require('protractor');

async function setupTest() {
  // Create your raw Selenium driver instance
  const driver = new Builder().forBrowser('chrome').build();

  // Bind the driver to Protractor's browser object
  protractor.browser.driver = driver;
  
  // If testing a non-Angular app, disable Angular synchronization (critical!)
  await protractor.browser.waitForAngularEnabled(false);

  // Expose $ and $$ globally to match Protractor's standard setup
  global.$ = protractor.$;
  global.$$ = protractor.$$;

  // Now you can use $ just like in a regular Protractor test
  await $('input#username').sendKeys('test-user');
}

// Clean up after the test
setupTest().finally(() => protractor.browser.quit());

Note: Protractor’s $ returns a promise-like ElementFinder, so always use await with it (especially since Protractor’s old control flow is deprecated in newer versions).


Solution 2: Use Native Selenium Locators (No Protractor Dependency)

If you don’t need Protractor’s extra Angular-focused features, you can stick to raw Selenium methods that work natively with your driver. This skips any Protractor-specific setup entirely:

const { Builder, By } = require('selenium-webdriver');

async function runTest() {
  const driver = new Builder().forBrowser('chrome').build();
  try {
    await driver.get('https://your-app-url.com');
    
    // Equivalent to Protractor's $: use By.css for CSS selectors
    const usernameInput = await driver.findElement(By.css('input#username'));
    await usernameInput.sendKeys('test-user');

    // Equivalent to Protractor's $$: find multiple elements
    const allButtons = await driver.findElements(By.css('button'));
    console.log(`Found ${allButtons.length} buttons on the page`);
  } finally {
    await driver.quit();
  }
}

runTest();

You can even wrap these into your own $/$$ functions to mimic Protractor’s syntax if you prefer:

const { By } = require('selenium-webdriver');
let driver; // Your initialized Selenium driver instance

async function $(selector) {
  return await driver.findElement(By.css(selector));
}

async function $$(selector) {
  return await driver.findElements(By.css(selector));
}

// Usage example:
await $('input#username').sendKeys('test-user');

Why You Might Have Seen "$ is not a function"

If you tried configuring Protractor before but hit this error, it’s probably due to one of these issues:

  • You didn’t properly bind your Selenium driver to Protractor’s browser object.
  • You forgot to handle the asynchronous nature of Protractor’s $ (e.g., missing await in an async function).
  • You’re testing a non-Angular app and didn’t disable Protractor’s automatic Angular synchronization, causing timing conflicts.

内容的提问来源于stack exchange,提问作者Jesus is Lord

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:54:49