sodcalculator

10 Tech How-To

Jasmine with Selenium: JS Testing Guide

Guide 10-33386 · Updated · Step by step

This guide walks you through combining Jasmine, a popular behavior-driven development (BDD) testing framework, with Selenium WebDriver to run automated browser tests for your JavaScript applications. You’ll learn how to set up the environment, write test specs that interact with a real browser, and handle common pitfalls. By the end, you’ll be able to run a suite of browser tests that verify your app’s behavior end-to-end.

What You’ll Need

  • Node.js and npm installed (LTS version recommended)
  • A code editor (VS Code, Atom, etc.)
  • Basic knowledge of JavaScript and writing tests with Jasmine
  • Chrome or Firefox browser installed (for local WebDriver execution)

Step-by-Step

  1. Initialize your project
    Create a new directory for your project and run npm init -y to generate a package.json file.
  2. Install Jasmine and Selenium WebDriver
    Run the following command to install the required packages:
    npm install --save-dev jasmine selenium-webdriver
    For Chrome, also install the driver manager: npm install --save-dev chromedriver (or geckodriver for Firefox).
  3. Initialize Jasmine
    Run npx jasmine init to create the default Jasmine configuration and spec directory. This creates spec/support/jasmine.json where you can configure the test environment.
  4. Configure Jasmine to use Selenium
    Edit spec/support/jasmine.json to include a helpers array that points to a file where you’ll set up the Selenium driver. For example, add "helpers": ["helpers/*.js"].
  5. Create a Selenium helper
    In the spec/helpers directory, create a file named selenium.js. This file will export a function that creates a WebDriver instance. A basic example:
    const { Builder } = require('selenium-webdriver');
    
    async function createDriver() {
      let driver = await new Builder().forBrowser('chrome').build();
      return driver;
    }
    
    module.exports = { createDriver };
    
  6. Write your first test spec
    In the spec directory, create a file like example.spec.js. Use Jasmine’s describe and it blocks. Inside the test, create a driver, navigate to a URL, interact with elements, and assert expected behavior. Example:
    const { createDriver } = require('./helpers/selenium');
    
    describe('Homepage', function() {
      let driver;
    
      beforeEach(async function() {
        driver = await createDriver();
        await driver.get('https://example.com');
      });
    
      afterEach(async function() {
        await driver.quit();
      });
    
      it('should have the correct title', async function() {
        const title = await driver.getTitle();
        expect(title).toBe('Example Domain');
      });
    
      it('should display a heading', async function() {
        const heading = await driver.findElement({css: 'h1'}).getText();
        expect(heading).toContain('Example');
      });
    });
    
  7. Run the tests
    Execute npx jasmine in your terminal. The tests will launch a browser window, perform the actions, and report results in the console.
  8. Handle async properly
    Jasmine supports async/await natively. Always await Selenium promises (like driver.get(), findElement(), getText()) to avoid race conditions.
  9. Add more complex interactions
    Use Selenium’s WebDriver API to click buttons, type into inputs, wait for elements, and take screenshots. For example:
    await driver.findElement({name: 'q'}).sendKeys('Selenium');
    await driver.findElement({name: 'btnK'}).click();
    await driver.wait(until.elementLocated({css: 'h3'}), 10000);
    
  10. Use waits to handle dynamic content
    Instead of fixed sleeps, use driver.wait() with until conditions (e.g., until.elementLocated, until.elementIsVisible) to make tests stable.

Common Mistakes

  • Forgetting to await Selenium calls – Selenium WebDriver returns promises. Not awaiting them leads to tests passing randomly or failing with “Thenable” errors.
  • Not closing the driver – Failing to call driver.quit() in afterEach leaves browser processes running, slowing down subsequent tests.
  • Using brittle selectors – Relying on absolute XPath or dynamic CSS classes can break tests when the UI changes. Prefer stable IDs or data attributes.
  • Ignoring waits – Using Thread.sleep() or hard-coded delays makes tests slow and flaky. Use explicit waits.
  • Mixing Jasmine and Mocha syntax – Ensure you’re using Jasmine’s expect and not Chai or other assertion libraries without proper setup.

Tips

  • Keep your tests independent – each spec should not rely on state from previous tests.
  • Use a page object model to encapsulate selectors and actions, making tests more readable and maintainable.
  • Run tests in headless mode for CI environments by adding chromeOptions with args: ['--headless'].
  • Use Jasmine’s jasmine.DEFAULT_TIMEOUT_INTERVAL to increase the timeout for slow operations (e.g., set to 30000 ms).
  • Leverage afterAll to clean up global resources, but keep driver creation per test to avoid shared state.

Troubleshooting

  • “SessionNotCreatedError: This version of ChromeDriver only supports Chrome version XX” – Your chromedriver version doesn’t match your Chrome browser. Update both to the latest versions using npm install chromedriver@latest and ensure Chrome is updated.
  • Tests hang or time out – Often due to missing waits. Add explicit waits for elements that load asynchronously. Also check that your beforeEach and afterEach are properly awaited.
  • “NoSuchElementError” – The element isn’t found. Double-check the selector and ensure the page has loaded. Use driver.wait(until.elementLocated(...)) before interacting.
  • Jasmine doesn’t recognize async tests – Make sure your Node version supports async/await (Node 8+). Also, avoid using done() callbacks with async functions; mix them carefully.
  • Port conflicts – If you get “EADDRINUSE”, another process is using the default port. Set a custom port via driver.manage().window().setSize()? Actually, for Selenium, use a free port by not specifying one; if using a grid, check the hub configuration.

Frequently Asked Questions

  1. Can I use Jasmine with Selenium for unit testing? – Yes, but Jasmine is primarily for unit tests. For end-to-end browser tests, Selenium is the right tool. You can combine them, but it’s often better to keep unit tests separate from integration tests.
  2. Do I need a Selenium server? – No, using selenium-webdriver with the chromedriver package runs a standalone server automatically. For remote execution, you’d need a Selenium Grid.
  3. How do I run tests in Firefox? – Install geckodriver and change the browser in the Builder to 'firefox'. Ensure the geckodriver version matches your Firefox version.
  4. Can I test multiple pages in one spec? – Yes, you can navigate to different URLs within the same it block, but it’s better to keep each test focused on one behavior.
  5. How do I take screenshots on failure? – Use driver.takeScreenshot() in the afterEach or in a custom Jasmine reporter. Save the base64 string to a file.
  6. Is it possible to run tests in parallel? – Jasmine doesn’t support parallel execution natively. You can use jasmine-parallel or run multiple processes, but be careful with shared browser resources.

Related

General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.

More in this bed

The whole Tech How-To bed →