Проверка на наличие свойств объекта

В тестах на Protractor регулярно возникает необходимость проверять структуру и состав объектов: конфигураций, ответов API, моделей Page Object, параметров браузера, пользовательских данных и вспомогательных структур. Корректная проверка наличия свойств позволяет выявлять ошибки на раннем этапе и делать тесты устойчивыми к изменениям.


Объекты в контексте Protractor

В Protractor используются разные типы объектов:

  • Page Object — объекты с методами и свойствами, описывающими страницу
  • Результаты выполнения скриптов (browser.executeScript)
  • Конфигурационные объекты (browser.params, capabilities)
  • Данные, полученные из API
  • Вспомогательные структуры, используемые в тестовой логике

Проверка наличия свойств относится именно к JavaScript-объектам, а не к DOM-элементам или атрибутам HTML.


Проверка через оператор in

Оператор in определяет, существует ли свойство в объекте или его прототипе.

const user = {
  name: 'Ivan',
  role: 'admin'
};

expect('name' in user).toBe(true);
expect('toString' in user).toBe(true);

Особенности:

  • Возвращает true, даже если свойство унаследовано
  • Подходит для случаев, когда важен сам факт доступности свойства

Использование оправдано при проверке стандартных API или объектов, где прототипная цепочка имеет значение.


Проверка через hasOwnProperty

Метод hasOwnProperty определяет, является ли свойство собственным.

expect(user.hasOwnProperty('name')).toBe(true);
expect(user.hasOwnProperty('toString')).toBe(false);

Ключевые моменты:

  • Игнорирует унаследованные свойства
  • Предпочтителен при проверке структуры данных
  • Может быть переопределён внутри объекта

Для безопасного вызова используется форма через прототип:

Object.prototype.hasOwnProperty.call(user, 'name');

Проверка на undefined

Простейший способ — проверить, что свойство не равно undefined.

expect(user.name).not.toBeUndefined();

Ограничения:

  • Не различает отсутствие свойства и явно заданное undefined
  • Может давать ложноположительные результаты
const obj = { value: undefined };
'value' in obj;           // true
obj.value === undefined;  // true

Проверка вложенных свойств

В тестах часто встречаются вложенные структуры, особенно при работе с API.

const response = {
  data: {
    user: {
      id: 10,
      email: 'test@mail.com'
    }
  }
};

Прямая проверка может привести к ошибке:

response.data.user.email

Безопасные подходы:

Пошаговая проверка

expect(response.data).toBeDefined();
expect(response.data.user).toBeDefined();
expect(response.data.user.email).toBeDefined();

Использование опциональной цепочки

expect(response.data?.user?.email).toBeDefined();

Поддерживается в современных версиях Node.js и значительно упрощает код.


Проверка структуры Page Object

Page Object часто содержит элементы и методы, наличие которых критично для тестов.

class LoginPage {
  constructor() {
    this.usernameInput = element(by.id('username'));
    this.passwordInput = element(by.id('password'));
    this.submitButton = element(by.buttonText('Login'));
  }

  login(user, pass) {
    this.usernameInput.sendKeys(user);
    this.passwordInput.sendKeys(pass);
    this.submitButton.click();
  }
}

Проверка структуры:

expect(loginPage.hasOwnProperty('usernameInput')).toBe(true);
expect(loginPage.hasOwnProperty('login')).toBe(true);

Такие проверки полезны при динамической генерации страниц или при рефакторинге.


Проверка параметров browser.params

Конфигурационные параметры часто используются для управления логикой тестов.

// protractor.conf.js
params: {
  env: 'test',
  apiUrl: 'https://api.example.com'
}

Проверка в тесте:

expect(browser.params.hasOwnProperty('env')).toBe(true);
expect(browser.params.env).toBe('test');

Это позволяет валидировать корректность конфигурации перед выполнением тестов.


Проверка свойств объекта capabilities

Объект capabilities описывает среду выполнения браузера.

browser.getCapabilities().then(caps => {
  expect(caps.has('browserName')).toBe(true);
  expect(caps.get('browserName')).toBe('chrome');
});

Здесь используется API Capabilities, а не обычный объект, но логика проверки аналогична.


Отличие свойств объекта от атрибутов DOM

Важно не путать:

  • Свойства JavaScript-объекта
  • Атрибуты HTML-элемента
const input = element(by.id('username'));

Проверка атрибута:

expect(input.getAttribute('type')).toBeDefined();

Это не проверка свойства объекта, а асинхронный запрос к DOM.


Проверка динамически добавляемых свойств

В тестах может использоваться расширение объектов во время выполнения.

const context = {};

context.user = { id: 1 };

Проверка:

expect('user' in context).toBe(true);

При динамической логике предпочтительнее использовать in, так как структура может меняться.


Типичные ошибки

Использование obj.property !== undefined как универсального решения Не различает отсутствие свойства и значение undefined.

Проверка вложенных свойств без защиты Приводит к TypeError.

Ожидание DOM-элемента как свойства объекта ElementFinder — это объект-обёртка, а не DOM-узел.


Практические рекомендации

  • Для проверки структуры данных использовать hasOwnProperty
  • Для вложенных свойств применять опциональную цепочку
  • Для конфигурационных объектов проверять наличие ключей до использования
  • Не смешивать проверку свойств объектов и атрибутов DOM
  • В Page Object явно контролировать наличие ключевых полей

Корректная проверка наличия свойств объекта повышает надёжность тестов, упрощает сопровождение и снижает количество ложных падений при изменении логики или данных.