Roku Сервис
wdio-roku-service — это сторонний пакет, для получения дополнительной информации, пожалуйста, посетите GitHub | npm Этот сервис переопределяет многие части WebdriverIO, чтобы обеспечить их использование с приложениями Roku, и предоставляет доступ к Roku ECP для управления Roku во время тестирования.
Требования
Roku
Тестовый канал/channel.zip и устройство Roku (с включенным режимом разработчика) в той же сети, что и ваш Mac.
WebdriverIO
Это не самостоятельный продукт — он используется как плагин для т естирования WebdriverIO (или Сервис, на их языке). Перед использованием вы должны пройти настройку WDIO, запустив npm init wdio@latest
.
При прохождении этапов настройки, чтобы не пришлось проходить через все вопросы/варианты, вы можете просто выбрать следующие пункты во время фазы инициализации:
- Roku Testing (ПРИМЕЧАНИЕ: Используйте это, если ваш репозиторий будет использоваться только для тестирования Roku, так как он станет сервисом по умолчанию и единственным установленным сервисом. В противном случае используйте E2E Testing, чтобы вы могли установить несколько сервисов.)
- On my local machine (только для E2E)
- Web (только для E2E)
- Chrome (только для E2E)
- Mocha
- Typescript [modules работает как для TS, так и для JS, так что выбирайте любой]
- autogenerate some test files (Y) -- default location
- page objects (Y) -- default location
- spec reporter
- additional plugins (N)
- Visual Testing (N)
- services (roku)
- npm install (Y)
Typescript Config
Если вы хотите использовать Typescript для написания тестов, вам необходимо убедиться, что следующие параметры ус тановлены в файле tsconfig.json, сгенерированном Webdriverio.
"moduleResolution": "nodenext",
"module": "NodeNext",
Затем вы можете использовать сервис, импортируя его в свои тесты, как описано ниже.
WDIO Config
В настоящее время тестирование поддерживается только для одного устройства Roku. Требуются следующие обновления конфигурации:
maxInstances
иmaxInstancesPerCapability
должны быть равны 1. Автоматическое тестирование на нескольких устройствах не поддерживается и приведет к дублированию команд, отправляемых на Roku. Должна быть только одна возможность.
//wdio.conf.js
export const config: WebdriverIO.Config = {
maxInstances: 1,
capabilities: [{
browserName: 'chrome'
// или если вы хотите режим headless:
browserName: 'chrome',
'goog:chromeOptions': {
args: ['--headless', '--disable-gpu']
}
}],
//...
}
- Рекомендуется увеличить
waitforInterval
иwaitforTimeout
, так как каждый интервал включает загрузку xml с Roku. Чтобы получить больше от функцииbrowser.debug()
, вы также можете расширить тайм-аут тестового раннера mocha до 5+ минут для разработки.
//wdio.conf.js
export const config: WebdriverIO.Config = {
waitforTimeout: 30000,
//optional:
mochaOpts: {
ui: 'bdd',
timeout: 600000
},
//...
}
Вы готовы написать свой первый тест!
import { installFromZip } from 'wdio-roku-service/install'
import { exitChannel } from 'wdio-roku-service/channel'
import { Buttons, keyPress, keySequence } from 'wdio-roku-service/controller'
describe('first test', () => {
before('On the landing screen of the test channel', async () => {
await installFromZip(process.env.ROKU_APP_PATH)
})
it('should launch to the homescreen without login', async () => {
await $("//LoadingIndicator").waitForDisplayed({ reverse: true })
await expect($("//ContentCarousel")).toBeDisplayed()
})
after('should return to home', async () => {
await exitChannel()
})
})
Также рекомендуется использовать функцию browser.debug()
в wdio для остановки теста для отладки и создания тестов:
// ...
it('should launch to the homescreen without login', async () => {
await $("//LoadingIndicator").waitForDisplayed({ reverse: true })
await expect($("//ContentCarousel")).toBeDisplayed()
await browser.debug()
// тест останавливается, становится доступен REPL для команд
Если chrome не в режиме headless, вы можете увидеть последний раз, когда была вызвана openRokuXML()
(вероятно, через waitForX
или expect
). Используя REPL в вашем терминале, вы можете использовать любые допустимые команды $
и несколько ключевых пользовательских команд (browser.openRokuXML()
и browser.saveScreenshot('path/to/ss.jpg')
) -- класс controller
не прикреплен к объекту browser
, поэтому вы не можете использовать их в данный момент. К счастью, вы, вероятно, сидите рядом с Roku и у вас есть пульт, который вы можете использовать для навигации и иногда вызывать browser.openRokuXML()
, чтобы увидеть, что произошло с состоянием страницы! И помните, что XML работает нативно с xpath в самом браузере chrome, поэтому вы можете непосредственно оценивать/разрабатывать свои селекторы в консоли chrome во время отладки.
.env
См. файл .env.example
. Скопируйте его и переименуйте в .env
в вашем проекте WebdriverIO, который использует этот сервис. Возможно, вы также захотите добавить его в .gitignore.
ROKU_IP
должен быть IP-адресом вашего Roku. Команды будут использовать этот IP для связи с ним. Это обязательно.ROKU_USER
иROKU_PW
: Учетные данные для входа необходимы д ля установки архива, а также для создания скриншотов.ROKU_APP_PATH
должен быть абсолютным путем к zip-файлу канала Roku.ROKU_CHANNEL_ID
должен быть ID вашего канала Roku (обычно это "dev").DEBUG=wdio-roku-service
включит отладочные сообщения. Удалите символ '#' в начале строки, если вы хотите их видеть.
Измененные функции
Browser
waitUntil
будет получать xml с Roku при каждой итерации, чтобы проверить изменения.saveScreenshot
загрузит скриншот текущего экрана с Roku. Примечательно, что эти скриншоты имеют формат .jpg, а не .png, который обычно использует WebdriverIO.openRokuXML
получит xml с Roku, если вам нужно сделать это вручную, а не с помощью ожиданий.
Elements
- Все ожидания поддерживаются так же, как и Browser.
waitForClickable
сопоставляется сwaitForDisplayed
, аwaitForStable
сопоставляется сwaitForExist
. click
,doubleClick
иmoveTo
не поддерживаются. Вы должны вручную перемещаться по приложению.isFocused
проверит наличие атрибутаfocused
на элементе, равного true.isDisplayed
проверит наличие атрибутаbounds
на элементе и чтоvisible
не установлен на false. Если установленwithinViewport
, границы будут сравниваться с размером экрана Roku.getSize
иgetLocation
берут значения из атрибутаbounds
, возвращая 0 для размера и -Infinity для позиции, если они отсутствуют.
Другие функции не изменились, но многие по-прежнему работают как ожидалось.
Matchers
Большинство матчеров были обновлены для получения xml во время ожидания. Некоторые имеют немного другую функциональность.
toBeDisplayed
,toBeDisplayedInViewport
,toBeFocused
,toBeExisting
,toBePresent
,toExist
,toHaveSize
,toHaveWidth
,toHaveHeight
иtoHaveAttribute
работают как ожидается, с учетом изменений в Element.toHaveElementProperty
сопоставляется сtoHaveAttribute
.toHaveElementClass
проверяет атрибутname
элемента.toHaveId
сопоставляется сtoHaveElementClass
.toHaveText
проверяет атрибутtext
элемента.toHaveChildren
проверяет атрибутchildren
элемента.toHaveHTML
будет обрабатывать xml так, как если бы это был HTML, хотя, вероятно, это не очень полезно.
Следующие функции в настоящее время не поддерживаются:
toBeSelected
- Может быть поддержано в ближайшее время после определения того, как выглядит xml для выбранных кнопок, если есть разница.toBeChecked
- Может быть поддержано в ближайшее время после определения того, как выглядит xml для отмеченных флажков, если есть разница.toHaveComputedLabel
- Если у вас есть эквивалент этого на ваших элементах Roku, проверьте атрибут с помощьюtoHaveAttribute
.toHaveComputedRole
- Если у вас есть эквивалент этого на ваших элементах Roku, проверьте атрибут с помощьюtoHaveAttribute
.toHaveHref
- Если у вас есть URL на ваших элементах Roku, проверьте атрибут с помощьюtoHaveAttribute
.toHaveStyle
- Элементы xml не имеют стилей.toHaveClipboardText
- Это неизвестно.toHaveTitle
- Заголовком будет случайно сгенерированное временное имя файла xml.toHaveUrl
- URL будет путем к файлу xml на вашем компьютере.
Использование
Установка канала
Это требует, чтобы ваш канал имел назначенный ID.
import { installByID } from 'wdio-roku-service/install';
async before() {
await installByID(process.env.ROKU_CHANNEL_ID);
}
Установка архива
Рекомендуется хранить путь в .env, особенно если у вас несколько разработчиков, которые могут иметь разные расположения и/или имена файлов.
import { installFromZip } from 'wdio-roku-service/install';
async before() {
await installFromZip(process.env.ROKU_ARCHIVE_PATH);
}
Предустановленный канал
Если вы уже установили канал самостоятельно до тестирования, вы можете просто запустить его.
import { launchChannel, exitChannel } from 'wdio-roku-service/channel';
async before() {
// Закройте канал, если он уже открыт. Если канал поддерживает быстрое возобновление, это просто переместит его в фоновый режим
await exitChannel();
// Использование ID канала 'dev' запустит боковую загрузку приложения.
await launchChannel('dev');
}
Тестирование
wdio-roku-service/controller
предоставляет возможность отправлять нажатия кнопок на Roku. keySequence
— это основная функция, отправляющая несколько нажатий кнопок последовательно.
import { Buttons, keySequence } from 'wdio-roku-service/controller';
// Навигация по приложению
await keySequence(Buttons.LEFT, Buttons.LEFT, Buttons.SELECT, Buttons.DOWN, Buttons.SELECT);
// Получение текущего UI приложения с Roku и загрузка его в браузер
await browser.openRokuXML();
// Или используйте ожидания, которые будут неоднократно загружать XML до истечения тайм-аута или выполнения условия
await browser.waitUntil(condition);
await element.waitForDisplayed();
// используйте матчеры WDIO для roku XML, как если бы это была веб-страница
await expect(element).toHaveAttr('focused');
wdio-roku-service/controller
также имеет функции для удержания или отпускания кнопок, а также ввода текста на клавиатуре.
import { Buttons, keyboardInput, keyPress, keySequence } from 'wdio-roku-service/controller';
await keySequence(Buttons.DOWN, Buttons.DOWN, Buttons.SELECT);
await keyboardInput('example');
await keyPress(Buttons.ENTER);
await browser.openRokuXML();
Deeplinking
wdio-roku-service/channel
предоставляет функциональность, связанную с каналом. inputChannel
позволяет отправлять произвольную информацию в ваше приложение.
import { exitChannel, launchChannel, MediaType } from 'wdio-roku-service/channel';
await exitChannel();
await launchChannel(process.env.ROKU_CHANNEL_ID, myContent, MediaType.MOVIE, {myExtraParameter:true});
await expect(MyContent.header).toBeDisplayed();
Другие функции
wdio-roku-service/info
предоставляет разнообразную функциональность, такую как получение иконки приложения или осиротевших узлов.
import { getAppIcon } from 'wdio-roku-service/info';
const response = await getAppIcon(process.env.ROKU_CHANNEL_ID);
expect(response.headers.get('Content-Type')).toBe('image/jpg');
wdio-roku-service/ecp
— это прямой интерфейс с ECP, если вам нужно сделать что-то очень специфическое.
import { ECP } from 'wdio-roku-service/ecp';
await ECP('search/browse?keyword=voyage&type=movie&tmsid=MV000058030000', 'POST');