Examples

Jest Integration

Complete example of using nut.js with Jest for end-to-end desktop automation testing

jesttestinge2e

This example demonstrates how to integrate nut.js with Jest to create robust end-to-end tests for desktop applications.

Project Setup

First, install the required dependencies:

bash
npm install --save-dev jest @types/jest ts-jest @nut-tree/nut-js @nut-tree/bolt @nut-tree/nl-matcher

Jest Configuration

Create a jest.config.js file:

javascript
/** @type {import('jest').Config} */
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  testTimeout: 30000, // Desktop automation tests may take longer
  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}

Setup File

Create jest.setup.ts to configure nut.js globally:

typescript
import { keyboard, mouse, screen } from '@nut-tree/nut-js'

// Configure nut.js for testing
beforeAll(() => {
  // Set reasonable delays for test stability
  keyboard.config.autoDelayMs = 100
  mouse.config.autoDelayMs = 100
  mouse.config.mouseSpeed = 1000
})

// Optional: helper for ad-hoc screenshot debugging
export async function captureDebugScreenshot(name: string) {
  await screen.capture(`./screenshots/${name}-${Date.now()}.png`)
}

Example Test Suite

Here's a complete test file (calculator.test.ts):

typescript
import {
  keyboard,
  screen,
  Key,
  imageResource,
  sleep,
  windowWithTitle,
} from '@nut-tree/nut-js';
import {useBoltWindowFinder} from '@nut-tree/bolt';
import { useNlMatcher } from '@nut-tree/nl-matcher';

useNlMatcher();

describe('Calculator Application', () => {
  beforeAll(async () => {
    useBoltWindowFinder();

    // Launch the calculator (platform-specific)
    if (process.platform === 'darwin') {
      await keyboard.pressKey(Key.LeftSuper, Key.Space)
      await keyboard.releaseKey(Key.LeftSuper, Key.Space)
      await sleep(500)
      await keyboard.type('Calculator')
      await keyboard.type(Key.Enter)
    }
    // Wait for app to launch
    await screen.waitFor(windowWithTitle('Calculator'));
  })

  afterAll(async () => {
    // Close the calculator
    await keyboard.type(Key.LeftSuper, Key.Q)
  })

  it('should perform basic addition', async () => {
    // Type the calculation
    await keyboard.type('5+3')
    await keyboard.type(Key.Enter)

    // Wait for result
    await sleep(500)

    // Verify result is displayed (using image matching)
    const result = await screen.waitFor(imageResource('result-8.png'))
    expect(result).toBeDefined()
  })

  it('should clear the display', async () => {
    await keyboard.type('C')

    // Verify display is cleared
    const clearDisplay = await screen.waitFor(imageResource('clear-display.png'))
    expect(clearDisplay).toBeDefined()
  })
})

Using Jest Matchers

nut.js provides custom Jest matchers for more readable assertions:

typescript
import { screen, imageResource, jestMatchers } from '@nut-tree/nut-js'

expect.extend(jestMatchers);

describe('Visual Assertions', () => {
  it('should show the login button', async () => {
    await expect(screen).toShow(imageResource('login-button.png'))
  })

  it('should show element within timeout', async () => {
    await expect(screen).toWaitFor(imageResource('loading-complete.png'), 5000)
  })
})

Running Tests

Add a script to your package.json:

json
{
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch",
    "test:ci": "jest --ci --reporters=default --reporters=jest-junit"
  }
}

Run your tests:

bash
npm test

Tips for Stable Tests

  1. Use appropriate delays: Desktop applications need time to render, so either use static delays via sleep, or use screen.waitFor(...) to wait for elements to appear
  2. Use image resources: Store reference images in a dedicated folder
  3. Handle platform differences: Use process.platform for OS-specific logic
  4. Set reasonable timeouts: Default Jest timeout may be too short
  5. Clean up after tests: Always close applications in afterAll

Was this page helpful?