Прошло довольно много времени с тех пор, как я обещал сделать третью часть на страницах Nightwatch.js. Я хочу поблагодарить Мариссу, которая нашла время в своем плотном графике, чтобы связаться со мной по поводу этой части руководства. В последнее время у меня на столе было много вещей, которые я не написал за три месяца. Я сожалею о том, что. Двигаемся дальше…

В этой статье я буду говорить о Page Objects. Без лишних слов, приступим.

Примечание. Большинство вещей, которые я здесь пишу, в основном то, что вы найдете в документации Nightwatch.js.

Что такое объект страницы?

Объект страницы позволяет программному клиенту делать что угодно и видеть все, что может сделать человек, путем абстрагирования от базовых действий HTML, необходимых для доступа к странице и управления ею.

Подробное введение в объекты страницы можно найти в этой статье.

Настроить объекты страницы

Чтобы настроить объекты страницы в nightwatch, нам нужно добавить свойство page_objects_path в наш nightwatch.json файл. Если вы посмотрите на это сейчас, то увидите, что мы это уже сделали. Если это не так, продолжайте и добавьте его в свой nightwatch.json файл конфигурации. Мы назначили ”pages” свойству page_objects_path в нашей конфигурации, при этом мы говорим Nightwatch читать объекты страницы из папки (или папок), указанной в свойстве конфигурации page_objects_path.

Вы также можете передать массив папок свойству page_objects_path, что позволяет разделить объекты страницы на более мелкие группы.

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

Свойство Url

Это свойство является необязательным, поскольку вы можете или не должны его указывать. Если предоставлен, он обозначает URL-адрес страницы. Вызовите метод navigate для объекта страницы, чтобы перейти на страницу.

URL-адрес обычно определяется как строка:

export default {
  url: 'https://cjdocs.herokuapp.com',
};

Вы также можете передать ему функцию в случае динамического URL-адреса. Один вариант использования - когда вы хотите поддерживать разные тестовые среды. Вы можете создать функцию, которая будет вызываться в контексте страницы, что позволит вам:

export default {
  url: function() { 
    return this.api.launchUrl + ‘auth/signin’; 
  },
};

Свойство Elements

Свойство elements используется для определения элементов на вашей странице, с которыми ваши тесты будут взаимодействовать с помощью команд и утверждений. Это помогает сохранить ваш код СУХИМ, особенно в больших интеграционных тестах.

В наших тестах нам не нужно вызывать useXpath или useCss, чтобы переключаться между стратегиями определения местоположения, поскольку это делается для нас внутри компании. По умолчанию для locateStrategy установлено значение CSS, но вы также можете указать XPath:

export default {
  elements: {
    searchBar: { 
      selector: ‘input[type=text]’ 
    },
    submit: { 
      selector: ‘//[@name=”q”]’, 
      locateStrategy: ‘xpath’ 
    }
  }
};

Вы можете использовать сокращение, если вы создаете элементы с той же стратегией определения местоположения, что и по умолчанию:

export default {
  elements: {
    searchBar: ‘input[type=text]’
  }
};

Используя свойство elements, мы можем ссылаться на элемент, добавляя префикс «@» к его имени, а не к селектору, при вызове команд и утверждений элемента (например, click и т. Д.).

При желании вы можете определить массив объектов:

var sharedElements = {
  mailLink: ‘a[href*=”mail.google.com”]’
};
export default {
  elements: [
    sharedElements,
    { searchBar: ‘input[type=text]’ }
  ]
};

Свойство Sections

Свойство sections позволяет определять разделы страницы. Это может быть полезно для двух вещей:

  1. Обеспечивает некоторый уровень пространства имен под страницей
  2. Он обеспечивает вложение на уровне элементов, так что любой элемент, определенный в разделе, является потомком своего родительского раздела в DOM

Создание раздела выглядит так:

export default {
  sections: {
    menu: {
      selector: ‘#gb’,
      elements: {
        mail: {
          selector: ‘a[href=”mail”]’
        },
        images: {
          selector: ‘a[href=”imghp”]’
        }
      }
    }
  }
};

Обратите внимание, что каждая команда и утверждение в разделе (кроме утверждений `expect`) возвращает этот раздел для объединения в цепочку. При желании вы можете вкладывать разделы в другие разделы для сложных структур DOM.

Свойство Commands

Свойство commands позволяет добавлять команды к объекту страницы. Это полезный способ инкапсулировать логику страницы, которая в противном случае жила бы в тесте или нескольких тестах.

Nightwatch вызовет команду в контексте страницы или раздела. Вы можете вызывать клиентские команды, например pause, через this.api. При связывании каждая функция должна возвращать объект или раздел страницы.

В приведенном ниже примере используется команда для инкапсуляции логики нажатия кнопки отправки:

const googleCommands = {
  submit: function() {
    this.api.pause(1000);
    return this.waitForElementVisible(‘@submitButton’, 1000)
      .click(‘@submitButton’)
      .waitForElementNotPresent(‘@submitButton’);
  }
};
export default {
  commands: [googleCommands],
  elements: {
    searchBar: {
      selector: ‘input[type=text]’
    },
    submitButton: {
      selector: ‘button[name=btnG]’
    }
  }
};

Это все свойства, доступные для объектов страницы. Пришло время увидеть некоторые из этих свойств в действии. Ура!
Я бы использовал свое приложение все еще в разработке здесь.

Написание тестов

Я буду тестировать страницу входа в приложение. Давайте продолжим и сделаем это.
Нам нужно будет создать файл подкачки в каталоге pages, который мы создали ранее. Я назвал свой signinPage.js и добавил его в каталог pages.

signinPage.js:

const signinCommands = {  
  signin(email, password) {
    return this
      .waitForElementVisible('@emailInput')
      .setValue('@emailInput', email)
      .setValue('@passwordInput', password)
      .waitForElementVisible('@signinButton')
      .click('@signinButton')
  }
};
export default {  
  url: 'https://cjdocs.herokuapp.com/auth/signin',
  commands: [signinCommands],
  elements: {
    emailInput: {
      selector: 'input[type=email]'
    },
    passwordInput: {
      selector: 'input[name=password]'
    },
    signinButton: {
      selector: 'button[type=submit]'
    }
  }
};

Затем мы создаем еще один объект страницы с именем instancesPage.js. Это будет использоваться, чтобы абстрагироваться от того, что мы будем искать, когда тест пройдет фазу аутентификации.

instancesPage.js:

export default {  
  elements: {
    homepageWelcomeTitle: {
      selector: '//div/h1',
      locateStrategy: 'xpath'
    }
  }
};

Наконец, мы должны создать наш тестовый файл с именем signin.spec.js.
signin.spec.js:

'User can sign in'(client) {
    const signinPage = client.page.signinPage();
    const instancesPage = client.page.instancesPage();
signinPage
      .navigate()
      .signin(process.env.EMAIL, process.env.PASSWORD);
instancesPage.expect.element('@homepageWelcomeTitle').text.to.contain('Welcome to the CJDocs Home!');
client.end();
}

После этого вы можете запускать тесты с помощью команды npm test или yarn test.

Вот и все, что нужно для использования объектов страницы. Полагаю, не так уж и сложно?

Заключение

Объекты страницы действительно помогают сделать наш код СУХИМ, тем самым абстрагируя некоторые общие функции в одном месте и просто вызывая эти определенные методы / свойства, и мы можем иметь полностью функциональные тесты без повторяющегося кода.

Надеюсь, вы узнали что-то новое сегодня. Если вам понравилось, нажмите кнопку «Нравится». Дайте мне знать в комментариях, если у вас есть вопросы или вы хотите, чтобы я что-то ответил.

О чем бы вы хотели, чтобы я написал? Имейте в виду то, что вы давно хотели узнать, напишите мне в личку, и я обязательно отвечу.

Вы можете найти меня в Twitter @codejockie.