Моки и стабы

Driver.js — это библиотека для создания интерактивных руководств по интерфейсу веб-приложений. Она позволяет выделять элементы страницы, сопровождать их подсказками и управлять последовательностью действий пользователя. Библиотека предоставляет гибкий API для настройки шагов, событий и визуального оформления.

Инициализация и базовая настройка

Для начала работы необходимо создать экземпляр класса Driver:

import Driver from 'driver.js';
import 'driver.js/dist/driver.min.css';

const driver = new Driver({
    animate: true,           // включение анимации перехода между шагами
    opacity: 0.75,           // затемнение фона
    padding: 10,             // отступ вокруг выделяемого элемента
    allowClose: false,       // запрет закрытия кликом вне подсказки
    doneBtnText: 'Готово',   // текст кнопки завершения
});

Ключевые опции:

  • animate — плавное перемещение подсказки.
  • opacity — прозрачность затемнения фона.
  • padding — расстояние между подсвечиваемым элементом и границами подсказки.
  • allowClose — разрешает пользователю закрывать тур кликом вне активного элемента.
  • doneBtnText и nextBtnText — пользовательские надписи для кнопок.

Создание шагов

Шаги задаются массивом объектов, где каждый объект содержит элемент и текст подсказки:

driver.defineSteps([
    {
        element: '#menu-button',
        popover: {
            title: 'Меню',
            description: 'Откройте меню для навигации по разделам.',
            position: 'bottom'
        }
    },
    {
        element: '#search-input',
        popover: {
            title: 'Поиск',
            description: 'Введите текст для поиска контента.',
            position: 'right'
        }
    }
]);

Параметры шага:

  • element — CSS-селектор или DOM-элемент.
  • popover.title — заголовок подсказки.
  • popover.description — описание действия.
  • popover.position — позиция подсказки относительно элемента (top, bottom, left, right).

Управление последовательностью

Driver.js предоставляет методы управления потоком:

driver.start();     // запуск тура
driver.moveNext();  // переход к следующему шагу
driver.movePrevious(); // переход к предыдущему шагу
driver.reset();     // сброс тура

Можно подписываться на события:

driver.on('next', (step) => {
    console.log('Переход к шагу', step);
});

driver.on('close', () => {
    console.log('Тур завершен');
});

Доступные события:

  • start — запуск тура.
  • next / previous — переход между шагами.
  • stop / close — завершение тура.
  • highlighted — элемент подсвечен.

Настройка внешнего вида

Driver.js поддерживает кастомизацию подсказок через CSS. Стандартные классы:

  • .driver-popover — контейнер подсказки.
  • .driver-button — кнопки управления.
  • .driver-opacity — затемненный фон.
  • .driver-target — подсвечиваемый элемент.

Можно менять цвета, шрифты, отступы и анимации через стили. Например:

.driver-popover {
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}

.driver-button {
    background-color: #007bff;
    color: #fff;
    border-radius: 4px;
}

Интеграция с динамическим контентом

Для SPA и страниц с динамической подгрузкой элементов важно убедиться, что целевой элемент присутствует в DOM перед подсветкой. Для этого можно использовать MutationObserver или асинхронное ожидание:

function waitForElement(selector, timeout = 5000) {
    return new Promise((resolve, reject) => {
        const interval = setInterval(() => {
            const el = document.querySelector(selector);
            if (el) {
                clearInterval(interval);
                resolve(el);
            }
        }, 100);

        setTimeout(() => {
            clearInterval(interval);
            reject(new Error('Элемент не найден'));
        }, timeout);
    });
}

await waitForElement('#dynamic-button');
driver.start();

Работа с моками и стабами

При тестировании интерактивных туров важно изолировать поведение подсказок. Моки и стабы позволяют:

  • Подменять функции driver.on для проверки вызовов без реального запуска анимации.
  • Подставлять фиктивные элементы DOM для тестирования шагов.
  • Контролировать события next и previous, чтобы имитировать пользовательские действия.

Пример стаба события next:

const mockNextHandler = jest.fn();
driver.on('next', mockNextHandler);

driver.moveNext();

expect(mockNextHandler).toHaveBeenCalledTimes(1);

Создание мок-элементов:

const mockElement = document.createElement('div');
mockElement.id = 'mock-button';
document.body.appendChild(mockElement);

driver.defineSteps([
    { element: '#mock-button', popover: { title: 'Тест', description: 'Описание' } }
]);

Продвинутые техники

  • Условные шаги: пропуск шагов в зависимости от состояния приложения.
if (!user.isLoggedIn) {
    driver.defineSteps([
        { element: '#login', popover: { title: 'Вход', description: 'Введите логин' } }
    ]);
}
  • Множественные туры: несколько экземпляров Driver для разных областей интерфейса.
  • API событий: подписка на highlighted позволяет логировать поведение пользователя.
driver.on('highlighted', (step) => {
    console.log(`Подсвечен элемент: ${step.element}`);
});
  • Асинхронные шаги: ожидание загрузки данных перед активацией подсказки.
driver.defineSteps([
    {
        element: '#async-element',
        popover: { title: 'Загрузка', description: 'Подождите данные' },
        onNext: async () => {
            await fetchData();
        }
    }
]);

Эта комбинация гибкого API, событийной модели и возможности работы с моками и стабами делает Driver.js мощным инструментом для создания интерактивных руководств и тестирования поведения интерфейсов в JavaScript.