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

В e2e-тестах на Protractor проверка типов данных имеет прикладное значение: она позволяет гарантировать, что интерфейс, бизнес-логика и взаимодействие с браузером работают с ожидаемыми структурами данных. Несмотря на динамическую природу JavaScript, в тестах необходимо явно контролировать, что значения, полученные из DOM, API или браузерного контекста, соответствуют ожидаемым типам.

Проверка типов особенно важна при:

  • работе с формами и пользовательским вводом;
  • проверке данных, отрендеренных Angular-приложением;
  • использовании асинхронных операций и Promise;
  • сравнении данных из разных источников (UI ↔︎ backend).

Источники данных в Protractor-тестах

В тестах на Protractor данные чаще всего поступают из следующих источников:

  • текст и значения элементов DOM;
  • атрибуты HTML-элементов;
  • данные из браузерного контекста (browser.executeScript);
  • параметры URL;
  • результаты асинхронных операций.

Каждый из этих источников имеет свои особенности с точки зрения типов.


Типы данных в JavaScript, с которыми работает Protractor

В тестах используются стандартные типы Jav * aScript:

  • string
  • number
  • boolean
  • undefined
  • null
  • object
  • array
  • function

Отдельного внимания требуют:

  • объекты, возвращаемые Protractor (ElementFinder, ElementArrayFinder);
  • значения, возвращаемые асинхронно;
  • данные, сериализуемые из браузера.

Проверка типов значений, полученных из DOM

Методы Protractor, работающие с элементами, почти всегда возвращают строки, даже если визуально данные выглядят как числа или логические значения.

const priceText = element(by.css('.price')).getText();

priceText — это строка, даже если отображается число 100.

Проверка типа строки

expect(typeof priceText).toBe('string');

Преобразование и проверка числового типа

const price = parseFloat(priceText);
expect(typeof price).toBe('number');
expect(isNaN(price)).toBe(false);

Проверка типов значений из input-элементов

Метод getAttribute('value') всегда возвращает строку.

const ageValue = element(by.name('age')).getAttribute('value');
expect(typeof ageValue).toBe('string');

Для проверки числового ввода необходимо явное преобразование:

const age = Number(ageValue);
expect(Number.isInteger(age)).toBe(true);

Проверка логических значений

Чекбоксы и переключатели требуют особого подхода. Их состояние определяется не значением value, а свойством isSelected().

const checkbox = element(by.id('agree'));
const isChecked = checkbox.isSelected();

expect(typeof isChecked).toBe('boolean');
expect(isChecked).toBe(true);

Проверка типов при работе с ElementFinder и ElementArrayFinder

Важно различать:

  • элемент как объект управления;
  • значение, полученное из элемента.
const button = element(by.buttonText('Save'));
expect(button instanceof ElementFinder).toBe(true);

Для массива элементов:

const rows = element.all(by.css('.table-row'));
expect(rows instanceof ElementArrayFinder).toBe(true);

Проверка количества элементов:

rows.count().then(count => {
  expect(typeof count).toBe('number');
});

Проверка типов в асинхронных операциях

Хотя современные версии Protractor поддерживают async/await, типы данных по-прежнему требуют явного контроля.

const title = await browser.getTitle();
expect(typeof title).toBe('string');

Для числовых значений:

const width = await element(by.css('.panel')).getSize().then(size => size.width);
expect(typeof width).toBe('number');

Проверка объектов и массивов

При получении сложных структур данных из браузерного контекста:

const data = await browser.executeScript(() => {
  return {
    name: 'Test',
    items: [1, 2, 3]
  };
});

Проверка типов:

expect(typeof data).toBe('object');
expect(Array.isArray(data.items)).toBe(true);
expect(typeof data.name).toBe('string');

Проверка null и undefined

Отличие между null и undefined критично в тестах.

expect(value).toBeNull();
expect(value).toBeUndefined();

Частый сценарий — отсутствие элемента:

const optionalElement = element(by.id('optional'));

optionalElement.isPresent().then(present => {
  expect(typeof present).toBe('boolean');
});

Проверка типов URL-параметров

Параметры URL всегда строки.

const currentUrl = await browser.getCurrentUrl();
const params = new URL(currentUrl).searchParams;
const page = params.get('page');

expect(typeof page).toBe('string');

При необходимости числовой проверки:

const pageNumber = parseInt(page, 10);
expect(Number.isInteger(pageNumber)).toBe(true);

Использование Jasmine-матчеров для проверки типов

Jasmine предоставляет базовые средства, которые можно комбинировать:

expect(value).toEqual(jasmine.any(String));
expect(value).toEqual(jasmine.any(Number));
expect(value).toEqual(jasmine.any(Boolean));
expect(value).toEqual(jasmine.any(Object));

Для массивов:

expect(value instanceof Array).toBe(true);

Пользовательские проверки типов

В сложных сценариях удобно выносить проверки в вспомогательные функции.

function isNonEmptyString(value) {
  return typeof value === 'string' && value.trim().length > 0;
}

expect(isNonEmptyString(username)).toBe(true);

Проверка типов в условиях ожиданий (ExpectedConditions)

При работе с ExpectedConditions важно помнить, что они возвращают логическое значение.

const EC = protractor.ExpectedConditions;
const visible = EC.visibilityOf(element(by.id('modal')));

expect(typeof visible).toBe('function');

Результат ожидания:

await browser.wait(EC.visibilityOf(modal), 5000);

Само ожидание не возвращает данные, но проверяет их состояние.


Типы данных и стабильность тестов

Явная проверка типов:

  • снижает количество ложных падений тестов;
  • упрощает отладку;
  • делает тесты самодокументируемыми;
  • предотвращает ошибки при рефакторинге UI и логики.

Контроль типов особенно важен в больших тестовых наборах, где один неверный тип может привести к каскадным сбоям во множестве сценариев.