├── CHANGELOG.md
├── LICENSE
├── README.md
├── RobotLibrary
├── Library
│ ├── RobotLibrary.py
│ ├── __init__.py
│ ├── variables.py
│ └── webDriver.py
├── Results
│ └── log.html
├── Tests
│ ├── Basic_tests.robot
│ ├── test_3_Grid.robot
│ ├── test_4_DetailsScreen.robot
│ ├── test_6_Encards.robot
│ ├── test_7_EpisodePickerScreen.robot
│ ├── test_7_EpisodePicker_focus.robot
│ ├── test_7_EpisodePicker_utils.robot
│ ├── test_9_Bookmarks.robot
│ ├── test_ParagraphView.robot
│ ├── test_Roku_Recommends.robot
│ ├── test_SearchView.robot
│ ├── test_TimeGridView.robot
│ ├── test_audio_mode.robot
│ ├── test_deepLinking.robot
│ ├── test_input.robot
│ ├── test_timer.robot
│ └── test_video_preloading.robot
├── channel.zip
├── multipleDevices
│ ├── Basic_tests_multi_device.robot
│ ├── config.json
│ ├── multi.py
│ ├── template.html
│ └── test_3_Grid_multi_device.robot
├── requirements.txt
├── setup.py
├── tutorialTests
│ ├── step_1.robot
│ ├── step_10.robot
│ ├── step_11.robot
│ ├── step_12.robot
│ ├── step_13.robot
│ ├── step_2.robot
│ ├── step_3.robot
│ ├── step_4.robot
│ ├── step_5.robot
│ ├── step_6.robot
│ ├── step_7.robot
│ ├── step_8.robot
│ └── step_9.robot
└── uTest
│ ├── _init_.py
│ ├── response_mock.py
│ ├── test_RobotLibrary.py
│ └── test_webDriver.py
├── bin
├── RokuWebDriver_linux
├── RokuWebDriver_mac
└── RokuWebDriver_win.exe
├── channels
├── 3_Grid.zip
├── 4_DetailsScreen.zip
├── 6_Endcards.zip
├── 7_EpisodePickerScreen.zip
├── 9_Bookmarks.zip
├── ParagraphView.zip
├── Roku_Recommends.zip
├── SearchView.zip
├── TimeGridView.zip
├── audio_mode.zip
└── video_preloading.zip
├── jsLibrary
├── library
│ ├── client.js
│ └── rokuLibrary.js
├── multipleDevices
│ ├── config.json
│ ├── multi.js
│ ├── multiple_devices_test_3-Grid.js
│ ├── multiple_devices_test_basics.js
│ ├── template.html
│ └── utils.js
├── package.json
├── tests
│ ├── test_3-Grid.js
│ ├── test_3-Grid_utils.js
│ ├── test_4-DetailsScreen.js
│ ├── test_6-Encards.js
│ ├── test_7-EpisodePicker.js
│ ├── test_7_EpisodePicker_focus.js
│ ├── test_9-Bookmarks.js
│ ├── test_ParagraphView.js
│ ├── test_Roku-Recommends.js
│ ├── test_Roku-Recommends_input.js
│ ├── test_Roku_Recommends_deepLinking.js
│ ├── test_SearchView.js
│ ├── test_TimeGridView.js
│ ├── test_audio-mode.js
│ ├── test_basic.js
│ └── test_video-preloading.js
└── uTest
│ ├── responses.js
│ ├── test_client.js
│ └── test_rokuLibrary.js
├── sample
├── Postman
│ ├── README.txt
│ └── WebDriver_endpoints
├── channel.zip
└── script
│ ├── main.py
│ ├── multipleDeviceSample.py
│ └── webDriver.py
└── src
├── ecpClient
├── ecp_client.go
├── ecp_client_test.go
├── ecp_parser.go
├── http_client.go
├── http_client_mock.go
├── response_mocks.go
└── response_structure.go
├── httpServer
├── handlers.go
├── handlers_test.go
├── middleware.go
├── response_mock.go
├── response_structure.go
├── routing.go
├── server.go
└── utils.go
├── main.go
└── version
└── version.go
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # **Roku Automated Channel Testing**
2 |
3 | ## v.2.3.0 (September 2021)
4 |
5 | ### Features
6 |
7 | * Added option to run the Roku WebDriver on a specific port.
8 |
9 | ### Bug Fixes
10 |
11 | * Fixed password validation for "/load" endpoint.
12 | * Updated Roku Recommends sample channel.
13 | * Adjusted sample tests that leverage Roku Recommends and SearchView channels.
14 |
15 | ## v.2.2.0 (April 2021)
16 |
17 | ### Features
18 |
19 | * Added pre-built WebDrivers for iOS, Linux, and Windows.
20 | * Added option for installing Python version of Robot library as a local Python package.
21 |
22 | ### Bug Fixes
23 |
24 | * Fixed submitting '@' symbol over "Send word" keyword.
25 | * Fixed "Get player info" keyword failing when called before playback starts
26 | * Adjusted sample tests for Robot and JS libraries (added **Sideload** command to automate sideloading of sample channels used for Robot and JavaScript sample tests).
27 |
28 | ## v.2.1.0 (July 2020)
29 |
30 | ### Features
31 |
32 | * Added "Get child nodes" method for Robot and JavaScript libraries.
33 | * Updated WebDriver **/element/active** endpoint to consistently return correct element.
34 | * Updated WebDriver **/elements** endpoint to returns correct elements when multiple locators are specified.
35 | * Added and updated sample tests for Robot and JavaScript libraries.
36 |
37 | ## v.2.0.0 (March 2020)
38 |
39 | ### Features
40 |
41 | * JavaScript client.
42 | * Channel side loading.
43 | * Input deep linking.
44 | * Timers.
45 | * Multiple device support for Robot and JavaScript libraries.
46 |
47 | ## v.1.0.0 (December 2019)
48 |
49 | ### Features
50 |
51 | * Initial Release
52 | * Initial version of a Roku WebDriver.
53 | * Key press simulation.
54 | * Grab UI elements.
55 | * Current app metadata.
56 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Roku Automated Channel Testing
2 | Copyright © 2019 Roku, Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
--------------------------------------------------------------------------------
/RobotLibrary/Library/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/RobotLibrary/Library/__init__.py
--------------------------------------------------------------------------------
/RobotLibrary/Library/variables.py:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2020 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | def get_variables():
18 | variables = {
19 | 'ip_address': '192.168.1.23',
20 | 'server_path': 'D:/projects/go/webDriver/src/main.exe',
21 | 'timeout': 20000,
22 | 'pressDelay': 2000
23 | }
24 | return variables
--------------------------------------------------------------------------------
/RobotLibrary/Library/webDriver.py:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | import requests
18 | import json
19 | from time import sleep
20 |
21 | class WebDriver:
22 | def __init__(self, roku_ip_address: str, timeout: int, pressDelay: int):
23 | data = {'ip' : roku_ip_address, 'timeout': timeout, 'pressDelay': pressDelay}
24 | request_url = self._build_request_url('')
25 | response = self._post(request_url, data)
26 | res = json.loads(response.text)
27 | self._session_id = res['sessionId']
28 |
29 | def send_launch_channel(self, channel_code: str, contentID, mediaType):
30 | data = {'channelId' : channel_code, 'contentId': contentID, 'contentType': mediaType}
31 | request_url = self._build_request_url(f"/{self._session_id}/launch")
32 | return self._post(request_url, data)
33 |
34 | def send_input_data(self, channelId, contentID, mediaType):
35 | data = {'channelId': channelId, 'contentId': contentID, 'contentType': mediaType}
36 | request_url = self._build_request_url(f"/{self._session_id}/input")
37 | return self._post(request_url, data)
38 |
39 | def get_device_info(self):
40 | request_url = self._build_request_url(f"/{self._session_id}")
41 | return self._get(request_url)
42 |
43 | def side_load(self, form):
44 | request_url = self._build_request_url(f"/{self._session_id}/load")
45 | return requests.post(request_url, files=form)
46 |
47 | def get_player_info(self):
48 | request_url = self._build_request_url(f"/{self._session_id}/player")
49 | return self._get(request_url)
50 |
51 | def send_install_channel(self, channel_code: str):
52 | data = {'channelId' : channel_code}
53 | request_url = self._build_request_url(f"/{self._session_id}/install")
54 | return self._post(request_url, data)
55 |
56 | def send_sequence(self, sequence):
57 | data = {'button_sequence' : sequence}
58 | request_url = self._build_request_url(f"/{self._session_id}/press")
59 | return self._post(request_url, data)
60 |
61 | def get_ui_element(self, data: object):
62 | request_url = self._build_request_url(f"/{self._session_id}/element")
63 | return self._post(request_url, data)
64 |
65 | def set_timeouts(self, timeoutType: str, delay: int):
66 | print(str(delay))
67 | data = {'type': timeoutType, 'ms': delay}
68 | request_url = self._build_request_url(f"/{self._session_id}/timeouts")
69 | return self._post(request_url, data)
70 |
71 | def get_ui_elements(self, data: object):
72 | request_url = self._build_request_url(f"/{self._session_id}/elements")
73 | return self._post(request_url, data)
74 |
75 | def get_apps(self):
76 | request_url = self._build_request_url(f"/{self._session_id}/apps")
77 | return self._get(request_url)
78 |
79 | def get_current_app(self):
80 | request_url = self._build_request_url(f"/{self._session_id}/current_app")
81 | return self._get(request_url)
82 |
83 | def get_screen_source(self):
84 | request_url = self._build_request_url(f"/{self._session_id}/source")
85 | return self._get(request_url)
86 |
87 | def send_keypress(self, key_press: str):
88 | data = {'button' : key_press}
89 | request_url = self._build_request_url(f"/{self._session_id}/press")
90 | return self._post(request_url, data)
91 |
92 | def get_active_element(self):
93 | request_url = self._build_request_url(f"/{self._session_id}/element/active")
94 | return self._post(request_url, {})
95 |
96 | def _build_request_url(self, endpoint: str):
97 | return f"http://localhost:9000/v1/session{endpoint}"
98 |
99 | def quiet(self):
100 | request_url = self._build_request_url(f"/{self._session_id}")
101 | return self._delete(request_url)
102 |
103 | def _post(self, request_url: str, data: object):
104 | return requests.post(url = request_url, data = json.dumps(data))
105 |
106 | def _get(self, request_url: str):
107 | return requests.get(request_url)
108 |
109 | def _delete(self, request_url: str):
110 | return requests.delete(request_url)
111 |
112 |
--------------------------------------------------------------------------------
/RobotLibrary/Tests/Basic_tests.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Basic smoke tests
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{DATA2}= using=text value=Barack Gates, Bill Obama
26 | @{DATA2Array}= &{DATA2}
27 | &{Params2}= elementData=${DATA2Array}
28 | &{DATA3}= using=text value=Please enter your username
29 | @{DATA3Array}= &{DATA3}
30 | &{Params3}= elementData=${DATA3Array}
31 | &{DATA4}= using=text value=Please enter your password
32 | @{DATA4Array}= &{DATA4}
33 | &{Params4}= elementData=${DATA4Array}
34 | @{KEYS}= down down down down select
35 | &{DATA5}= using=text value=Authenticate to watch
36 | @{DATA5Array}= &{DATA5}
37 | &{Params5}= elementData=${DATA5Array}
38 |
39 | *** Test Cases ***
40 | Channel should be launched
41 | Side load ../sample/channel.zip rokudev aaaa
42 | Verify is channel loaded ${channel_code}
43 |
44 | Check if details screen showed
45 | Send key select 4
46 | Verify is screen loaded ${Params2}
47 |
48 | Check if playback started
49 | ${status} ${value}= Run Keyword And Ignore Error Verify is screen loaded ${Params5} 2
50 | Run keyword if "${status}"=="PASS" Do auth
51 | ... ELSE Send key select
52 | Verify is playback started 20 2
53 |
54 | *** Keywords ***
55 | Do auth
56 | Send key select
57 | Verify is screen loaded ${Params3}
58 | Send word user
59 | Send keys ${KEYS}
60 | Verify is screen loaded ${Params4}
61 | Send word pass
62 | Send keys ${KEYS}
63 |
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_3_Grid.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{GridData}= using=tag value=GridView
26 | @{GridArray}= &{GridData}
27 | &{GridParams}= elementData=${GridArray}
28 | &{PosterData}= using=attr attribute=name value=poster
29 | @{PosterArray}= &{PosterData}
30 | &{PosterParams}= elementData=${PosterArray}
31 | ${poster1}= https://roku-blog.s3.amazonaws.com/developer/files/2017/04/Roku-Recommends-thumbnail.png
32 | ${poster2}= https://blog.roku.com/developer/files/2016/10/twitch-poster-artwork.png
33 |
34 | *** Test Cases ***
35 | Verify is channel launched
36 | Side load ../channels/3_Grid.zip rokudev aaaa
37 | Verify is channel loaded ${channel_code}
38 |
39 | Verify is initial screen loaded
40 | Verify is screen loaded ${GridParams}
41 |
42 | Verify posters
43 | @{elements}= Get elements ${PosterParams} 4
44 | :FOR ${ELEMENT} IN @{elements[0]['Attrs']}
45 | \ Run Keyword If "${ELEMENT['Name']['Local']}" == "uri" and "${ELEMENT['Value']}" != "${poster1}" Fail
46 | :FOR ${ELEMENT} IN @{elements[1]['Attrs']}
47 | \ Run Keyword If "${ELEMENT['Name']['Local']}" == "uri" and "${ELEMENT['Value']}" != "${poster2}" Fail
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_4_DetailsScreen.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{SeriesDetails}= using=text value=No Content to play
26 | @{SeriesDetailsArray}= &{SeriesDetails}
27 | &{SeriesDetailsParams}= elementData=${SeriesDetailsArray}
28 | &{Grid}= using=tag value=GridView
29 | @{GridArray}= &{Grid}
30 | &{GridParams}= elementData=${GridArray}
31 | &{MovieDetails}= using=text value=Play
32 | @{MovieDetailsArray}= &{MovieDetails}
33 | &{MovieDetailsParams}= elementData=${MovieDetailsArray}
34 |
35 | *** Test Cases ***
36 | Verify is channel launched
37 | Side load ../channels/4_DetailsScreen.zip rokudev aaaa
38 | Verify is channel loaded ${channel_code}
39 |
40 | Verify is initial screen loaded
41 | Verify is screen loaded ${GridParams}
42 |
43 | Verify series details screen button
44 | Send key Select 3
45 | Verify is screen loaded ${SeriesDetailsParams} 3 4
46 |
47 | Verify movies details screen button
48 | Send key Back 3
49 | Verify is screen loaded ${GridParams}
50 | Send key Down 3
51 | Send key Select 3
52 | Verify is screen loaded ${MovieDetailsParams}
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_6_Encards.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{GridData}= using=tag value=GridView
26 | @{GridArray}= &{GridData}
27 | &{GridParams}= elementData=${GridArray}
28 | &{DetailsData}= using=tag value=DetailsView
29 | @{DetailsArray}= &{DetailsData}
30 | &{DetailsParams}= elementData=${DetailsArray}
31 | &{EncardData}= using=text value=Play again
32 | @{EncardArray}= &{EncardData}
33 | &{EncardParams}= elementData=${EncardArray}
34 |
35 |
36 | *** Test Cases ***
37 | Verify is channel launched
38 | Side load ../channels/6_Endcards.zip rokudev aaaa
39 | Verify is channel loaded ${channel_code}
40 |
41 | Verify is initial screen loaded
42 | Verify is screen loaded ${GridParams}
43 |
44 | Verify is details screen loaded
45 | Send key Select 4
46 | Verify is screen loaded ${DetailsParams}
47 |
48 | Verify is playback started
49 | Send key Select 3
50 | Verify is playback started
51 |
52 | Encards
53 | Verify is screen loaded ${EncardParams} 10 10
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_7_EpisodePickerScreen.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{GridData}= using=tag value=GridView
26 | @{GridArray}= &{GridData}
27 | &{GridParams}= elementData=${GridArray}
28 | &{DetailsData}= using=tag value=DetailsView
29 | @{DetailsArray}= &{DetailsData}
30 | &{DetailsParams}= elementData=${DetailsArray}
31 | &{EncardData}= using=text value=Play again
32 | @{EncardArray}= &{EncardData}
33 | &{EncardParams}= elementData=${EncardArray}
34 | &{CategoryData}= using=tag value=CategoryListView
35 | @{CategoryArray}= &{CategoryData}
36 | &{CategoryParams}= elementData=${CategoryArray}
37 | &{tagData}= using=tag value=RenderableNode
38 | &{attrData}= using=attr attribute=focused value=true
39 | &{season1Data}= using=attr attribute=index value=0
40 | &{season2Data}= using=attr attribute=index value=1
41 | @{Season1Array}= &{tagData} &{attrData} &{season1Data}
42 | &{Season1Params}= elementData=${Season1Array}
43 | @{Season2Array}= &{tagData} &{attrData} &{season2Data}
44 | &{Season2Params}= elementData=${Season2Array}
45 | @{KEYS}= Down Down Down Down Down Down
46 |
47 | *** Test Cases ***
48 | Verify is channel launched
49 | Side load ../channels/7_EpisodePickerScreen.zip rokudev aaaa
50 | Verify is channel loaded ${channel_code}
51 |
52 | Verify is initial screen loaded
53 | Verify is screen loaded ${GridParams}
54 |
55 | Verify is details screen loaded
56 | Send key Select 4
57 | Verify is screen loaded ${DetailsParams}
58 |
59 | Verify is Categort list started
60 | Send key Select 4
61 | Verify is screen loaded ${CategoryParams}
62 |
63 | Verify is Season1 is focused
64 | Verify is screen loaded ${Season1Params}
65 |
66 | Verify is Season2 is focused
67 | Send keys ${KEYS}
68 | Verify is screen loaded ${Season2Params}
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_7_EpisodePicker_focus.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{GridData}= using=tag value=GridView
26 | @{GridArray}= &{GridData}
27 | &{GridParams}= elementData=${GridArray}
28 | &{DetailsData}= using=tag value=DetailsView
29 | @{DetailsArray}= &{DetailsData}
30 | &{DetailsParams}= elementData=${DetailsArray}
31 | &{EncardData}= using=text value=Play again
32 | @{EncardArray}= &{EncardData}
33 | &{EncardParams}= elementData=${EncardArray}
34 | &{CategoryData}= using=tag value=CategoryListView
35 | @{CategoryArray}= &{CategoryData}
36 | &{CategoryParams}= elementData=${CategoryArray}
37 | @{GridKeys}= Up Select
38 |
39 | *** Test Cases ***
40 | Verify is channel launched
41 | Side load ../channels/7_EpisodePickerScreen.zip rokudev aaaa
42 | Verify is channel loaded ${channel_code}
43 |
44 | Verify is initial screen loaded
45 | Verify is screen loaded ${GridParams}
46 |
47 | Verify focused element on grid screen
48 | Send key Down 4
49 | &{focusedEl}= get focusedElement
50 | @{Nodes}= Get From Dictionary ${focusedEl} Nodes
51 | ${uri}= Get attribute @{Nodes}[${1}] uri
52 | Run keyword if '${uri}'!='https://blog.roku.com/developer/files/2016/10/twitch-poster-artwork.png' Fail
53 |
54 | Verify is details screen loaded
55 | Send keys ${GridKeys} 4
56 | Verify is screen loaded ${DetailsParams}
57 |
58 | Verify focused element on details screen
59 | &{focusedEl}= get focusedElement
60 | @{Nodes}= Get From Dictionary ${focusedEl} Nodes
61 | @{Nodes}= Get From Dictionary @{Nodes}[${0}] Nodes
62 | ${text}= Get Attribute @{Nodes}[${2}] text
63 | Run keyword if '${text}'!='Episodes' Fail
64 |
65 | Verify is Categort list started
66 | Send key Select 4
67 | Verify is screen loaded ${CategoryParams}
68 |
69 | Verify focused element on episodes screen (episodes list)
70 | Send key Down
71 | &{focusedEl}= get focusedElement
72 | @{Nodes}= Get From Dictionary ${focusedEl} Nodes
73 | @{Nodes}= Get From Dictionary @{Nodes}[${1}] Nodes
74 | ${uri}= Get Attribute @{Nodes}[${0}] uri
75 | Run keyword if '${uri}'!='https://blog.roku.com/developer/files/2016/10/ted-poster-artwork.png' Fail
76 |
77 | Verify focused element on episodes screen (seasons list)
78 | Send key Left
79 | &{focusedEl}= get focusedElement
80 | @{Nodes}= Get From Dictionary ${focusedEl} Nodes
81 | @{Nodes}= Get From Dictionary @{Nodes}[${0}] Nodes
82 | ${text}= Get Attribute @{Nodes}[${2}] text
83 | Run keyword if '${text}'!='Season${SPACE*2}1' Fail
84 |
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_7_EpisodePicker_utils.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{GridData}= using=tag value=GridView
26 | @{GridArray}= &{GridData}
27 | &{OverhangData}= using=tag value=Overhang
28 | @{OverhangArray}= &{OverhangData}
29 | &{OVerhangParams}= elementData=${OverhangArray}
30 | &{GridParams}= elementData=${GridArray}
31 | &{DetailsData}= using=tag value=DetailsView
32 | @{DetailsArray}= &{DetailsData}
33 | &{DetailsParams}= elementData=${DetailsArray}
34 | &{PosterData}= using=tag value=Poster
35 | &{LabelData}= using=text value=Live Gaming
36 | &{IndexData}= using=attr attribute=index value=1
37 | @{LabelArray}= &{LabelData} &{IndexData}
38 | @{ParamArray}= &{PosterData}
39 |
40 | *** Test Cases ***
41 | Verify is channel launched
42 | Side load ../channels/7_EpisodePickerScreen.zip rokudev aaaa
43 | Verify is channel loaded ${channel_code}
44 |
45 | Verify is initial screen loaded
46 | Verify is screen loaded ${GridParams}
47 |
48 | Verify focused element on grid screen
49 | Send key Down 4
50 | &{focusedEl}= get focusedElement
51 | @{Nodes}= Get child nodes ${focusedEl} ${ParamArray}
52 | Log ${Nodes}
53 | ${uri}= Get attribute @{Nodes}[${0}] uri
54 | Run keyword if '${uri}'!='https://blog.roku.com/developer/files/2016/10/twitch-poster-artwork.png' Fail
55 |
56 | Verify is details screen loaded
57 | Send key Select 2
58 | Verify is screen loaded ${DetailsParams}
59 |
60 | Verify title on details screen
61 | &{Overhang}= get element ${OVerhangParams}
62 | @{Nodes}= Get child nodes ${Overhang} ${LabelArray}
63 | Log ${Nodes}
64 | ${count}= Get length ${Nodes}
65 | should be equal as numbers ${count} 1
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_9_Bookmarks.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{DetailsData}= using=tag value=DetailsView
26 | @{DetailsArray}= &{DetailsData}
27 | &{DetailsParam}= elementData=@{DetailsArray}
28 | @{KEYS}= Down Select
29 |
30 | *** Test Cases ***
31 | Verify is channel launched
32 | Side load ../channels/9_Bookmarks.zip rokudev aaaa
33 | Verify is channel loaded ${channel_code}
34 |
35 | Verify is details screen loaded
36 | Verify is screen loaded ${DetailsParam}
37 |
38 | Verify is playback started
39 | Send key Select 2
40 | Verify is playback started
41 |
42 | Bookmarks
43 | Sleep 12
44 | Send key Back
45 | Verify is screen loaded ${DetailsParam}
46 | Send keys ${KEYS} 3
47 | Verify is playback started
48 | &{player}= Get player info
49 | Run keyword if ${player['Position']} < 10000 Fail
50 |
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_ParagraphView.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{ParagraphViewData}= using=tag value=ParagraphView
26 | @{ParagraphViewArray}= &{ParagraphViewData}
27 | &{ParagraphViewParams}= elementData=${ParagraphViewArray}
28 | &{HeaderColorData}= using=attr attribute=color value=#22ffffff
29 | &{HeaderTextData}= using=text value=Header Text
30 | @{HeaderArray}= &{HeaderColorData} &{HeaderTextData}
31 | &{HeaderParams}= elementData=${HeaderArray}
32 | &{CodeIndexData}= using=attr attribute=index value=4
33 | &{CodeColorData}= using=attr attribute=color value=#ffff22ff
34 | @{CodeArray}= &{CodeColorData} &{CodeIndexData}
35 | &{CodeParams}= elementData=${CodeArray}
36 |
37 | *** Test Cases ***
38 | Verify is channel launched
39 | Side load ../channels/ParagraphView.zip rokudev aaaa
40 | Verify is channel loaded ${channel_code}
41 |
42 | Verify is initial screen loaded
43 | Verify is screen loaded ${ParagraphViewParams}
44 |
45 | Verify header color
46 | Verify is screen loaded ${HeaderParams}
47 |
48 | Verify reload linking code
49 | &{element}= Get element ${CodeParams}
50 | ${code}= Get attribute ${element} text
51 | Send key Select
52 | &{element2}= Get element ${CodeParams}
53 | ${newCode}= Get attribute ${element2} text
54 | Run Keyword If "${code}" == "${newCode}" Fail
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_Roku_Recommends.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 | *** Variables ***
23 | ${channel_code} dev
24 | &{DATA2}= using=text value=No Content to play
25 | @{Params2}= &{DATA2}
26 | &{Grid}= using=tag value=GridView
27 | @{GridArray}= &{Grid}
28 | &{GridParams}= elementData=${GridArray}
29 | &{Row}= using=tag value=Row
30 | @{RowArray}= &{Row}
31 | &{RowParams}= elementData=${RowArray}
32 |
33 |
34 | *** Test Cases ***
35 | Verify is channel launched
36 | Side load ../channels/Roku_Recommends.zip rokudev aaaa
37 | Verify is channel loaded ${channel_code}
38 |
39 | Verify is initial screen loaded
40 | Verify is screen loaded ${GridParams}
41 |
42 | Should be 3 Rows on Grid initially
43 | @{elements}= Get elements ${RowParams} 2
44 | ${len}= Get length ${elements}
45 | should be equal as numbers ${len} 3
46 |
47 | Should be 4 Rows on Grid after Down key press
48 | Send key Down
49 | @{elements}= Get elements ${RowParams} 2
50 | ${len}= Get length ${elements}
51 | should be equal as numbers ${len} 4
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_SearchView.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{SearchViewData}= using=tag value=SearchView
26 | @{SearchViewArray}= &{SearchViewData}
27 | &{SearchViewParams}= elementData=${SearchViewArray}
28 | &{PlaceholderTextData}= using=text value=Enter search term
29 | @{PlaceholderArray}= &{PlaceholderTextData}
30 | &{PlaceholderParams}= elementData=${PlaceholderArray}
31 | &{RowData}= using=tag value=Row
32 | @{RowDataArray}= &{RowData}
33 | &{RowParams}= elementData=${RowDataArray}
34 | &{ParentTagData}= using=tag value=TextEditBox
35 | @{ParentArray}= &{ParentTagData}
36 | &{ElementTagData}= using=tag value=Label
37 | @{ElementArray}= &{ElementTagData}
38 | &{LabelParams}= elementData=${ElementArray} parentData=${ParentArray}
39 | ${input}= hello@1 r~
40 |
41 | *** Test Cases ***
42 | Verify is channel launched
43 | Side load ../channels/SearchView.zip rokudev aaaa
44 | Verify is channel loaded ${channel_code}
45 |
46 | Verify is search screen loaded
47 | Verify is screen loaded ${SearchViewParams}
48 |
49 | Verify search input
50 | Verify is screen loaded ${PlaceholderParams}
51 | Send word ${input}
52 | &{label}= Get Element ${LabelParams}
53 | ${text}= Get attribute ${label} text
54 | Run Keyword If "${text}" != "${input}" Fail
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_TimeGridView.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{TimeGridViewData}= using=tag value=TimeGridView
26 | @{TimeGridViewArray}= &{TimeGridViewData}
27 | &{TimeGridViewParams}= elementData=${TimeGridViewArray}
28 | &{ParentTagData}= using=tag value=ChannelRow
29 | &{ParentIndexData}= using=attr attribute=index value=1
30 | @{ParentArray}= &{ParentTagData} &{ParentIndexData}
31 | &{ElementTagData}= using=tag value=Label
32 | @{ElementArray}= &{ElementTagData}
33 | &{LabelParams}= elementData=${ElementArray} parentData=${ParentArray}
34 | ${LabelValue}= KTVK-SD 3.2
35 |
36 | *** Test Cases ***
37 | Verify is channel launched
38 | Side load ../channels/TimeGridView.zip rokudev aaaa
39 | Verify is channel loaded ${channel_code}
40 |
41 | Verify is search screen loaded
42 | Verify is screen loaded ${TimeGridViewParams}
43 |
44 | Verify Label text
45 | &{element}= GetElement ${LabelParams}
46 | ${value}= Get attribute ${element} text
47 | Run Keyword If "${value}" != "${LabelValue}" Fail
48 |
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_audio_mode.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{GridData}= using=tag value=GridView
26 | @{GridArray}= &{GridData}
27 | &{GridParams}= elementData=${GridArray}
28 | &{DetailsData}= using=tag value=DetailsView
29 | @{DetailsArray}= &{DetailsData}
30 | &{DetailsParams}= elementData=${DetailsArray}
31 | &{EncardData}= using=text value=Play again
32 | @{EncardArray}= &{EncardData}
33 | &{EncardParams}= elementData=${EncardArray}
34 | &{CategoryData}= using=tag value=CategoryListView
35 | @{CategoryArray}= &{CategoryData}
36 | &{CategoryParams}= elementData=${CategoryArray}
37 | &{MediaViewData}= using=tag value=MediaView
38 | @{MediaViewArray}= &{MediaViewData}
39 | &{MediaViewParams}= elementData=${MediaViewArray}
40 | &{Item2Data}= using=text value=Item 1.2
41 | @{Item2Array}= &{Item2Data}
42 | &{Item2Params}= elementData=${Item2Array}
43 | @{KEYS}= Fwd Fwd Fwd Fwd Fwd
44 |
45 | *** Test Cases ***
46 | Verify is channel launched
47 | Side load ../channels/audio_mode.zip rokudev aaaa
48 | Verify is channel loaded ${channel_code}
49 |
50 | Verify is initial screen loaded
51 | Verify is screen loaded ${GridParams}
52 |
53 | Verify is details screen loaded
54 | Send key Select 4
55 | Verify is screen loaded ${DetailsParams}
56 |
57 | Verify is MediaView loaded
58 | Send key Select 4
59 | Verify is screen loaded ${MediaViewParams}
60 |
61 | Verify next content after FF
62 | Send keys ${KEYS} 4
63 | Verify is screen loaded ${Item2Params} 6 3
64 |
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_deepLinking.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Documentation Deep Linking
3 | Variables ./../Library/variables.py
4 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
5 | Library Collections
6 |
7 |
8 | *** Variables ***
9 | ${channel_code} dev
10 | ${content_id}= decbe34b64ea4ca281dc09997d0f23fd
11 | ${mediaType}= episode
12 |
13 | *** Test Cases ***
14 | Side load
15 | Side load ../channels/Roku_Recommends.zip rokudev aaaa
16 | Send key Home
17 |
18 | Verify is channel launched
19 | Launch the channel ${channel_code} ${content_id} ${mediaType}
20 | Verify is channel loaded ${channel_code}
21 |
22 | Verify is playback started
23 | Verify is playback started 25 2
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_input.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Documentation Deep Linking
3 | Variables ./../Library/variables.py
4 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
5 | Library Collections
6 |
7 |
8 | *** Variables ***
9 | ${channel_code} dev
10 | ${content_id}= decbe34b64ea4ca281dc09997d0f23fd
11 | ${mediaType}= episode
12 |
13 | *** Test Cases ***
14 | Side load
15 | Side load ../channels/Roku_Recommends.zip rokudev aaaa
16 |
17 | Verify is playback started
18 | Input deep linking data ${channel_code} ${content_id} ${mediaType}
19 | Verify is playback started 25 2
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_timer.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Documentation Deep Linking
3 | Variables ./../Library/variables.py
4 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
5 | Library Collections
6 |
7 |
8 | *** Variables ***
9 | ${channel_code} dev
10 | ${content_id}= decbe34b64ea4ca281dc09997d0f23fd
11 | ${content_id_input}= 6c9d0951d6d74229afe4adf972b278dd
12 | ${mediaType}= episode
13 |
14 | *** Test Cases ***
15 | Side load
16 | Side load ../channels/Roku_Recommends.zip rokudev aaaa
17 | Send key Home
18 |
19 | Verify is channel launched
20 | Launch the channel ${channel_code} ${content_id} ${mediaType}
21 | Mark timer
22 | Verify is channel loaded ${channel_code}
23 |
24 | Verify is playback started (Deep linking)
25 | Verify is playback started
26 |
27 | Verify is playback started quickly
28 | ${time_dl}= Get timer
29 | Run Keyword If ${time_dl} > 12000 Fail
30 |
31 | Verify is playback started (input)
32 | Send key Stop
33 | Sleep 2
34 | Mark timer
35 | Input deep linking data ${channel_code} ${content_id_input} ${mediaType}
36 | Verify is playback started 25 2
37 |
38 | Verify is playback(input) started quickly
39 | ${time_in}= Get timer
40 | Run Keyword If ${time_in} > 12000 Fail
41 |
--------------------------------------------------------------------------------
/RobotLibrary/Tests/test_video_preloading.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Variables ./../Library/variables.py
19 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
20 | Library Collections
21 |
22 |
23 | *** Variables ***
24 | ${channel_code} dev
25 | &{GridData}= using=tag value=GridView
26 | @{GridArray}= &{GridData}
27 | &{GridParams}= elementData=${GridArray}
28 | &{DetailsData}= using=tag value=DetailsView
29 | @{DetailsArray}= &{DetailsData}
30 | &{DetailsParams}= elementData=${DetailsArray}
31 | &{EncardData}= using=text value=Play again
32 | @{EncardArray}= &{EncardData}
33 | &{EncardParams}= elementData=${EncardArray}
34 |
35 | *** Test Cases ***
36 | Verify is channel launched
37 | Side load ../channels/video_preloading.zip rokudev aaaa
38 | Verify is channel loaded ${channel_code}
39 |
40 | Verify is initial screen loaded
41 | Verify is screen loaded ${GridParams}
42 |
43 | Verify is details screen loaded
44 | Send key Select 4
45 | Verify is screen loaded ${DetailsParams}
46 | &{player}= Get player info
47 | Log To Console ${player}
48 | Run keyword if '${player['State']}' != 'startup' Fail
49 |
50 | Verify is playback started
51 | Send key Select 4
52 | Verify is playback started
53 | &{player}= Get player info
54 | Log To Console ${player}
55 | Run keyword if '${player['State']}' != 'play' Fail
56 |
57 | Verify endcard after first video
58 | Verify is screen loaded ${EncardParams} 8 10
59 |
60 | Verify is playback started after 10 seconds
61 | Verify is playback started 3 5
62 |
--------------------------------------------------------------------------------
/RobotLibrary/channel.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/RobotLibrary/channel.zip
--------------------------------------------------------------------------------
/RobotLibrary/multipleDevices/Basic_tests_multi_device.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2020 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Basic smoke tests
18 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay}
19 | Library Collections
20 |
21 |
22 | *** Variables ***
23 | ${channel_code} dev
24 | &{DATA2}= using=text value=Barack Gates, Bill Obama
25 | @{DATA2Array}= &{DATA2}
26 | &{Params2}= elementData=${DATA2Array}
27 | &{DATA3}= using=text value=Please enter your username
28 | @{DATA3Array}= &{DATA3}
29 | &{Params3}= elementData=${DATA3Array}
30 | &{DATA4}= using=text value=Please enter your password
31 | @{DATA4Array}= &{DATA4}
32 | &{Params4}= elementData=${DATA4Array}
33 | @{KEYS}= down down down down select
34 | &{DATA5}= using=text value=Authenticate to watch
35 | @{DATA5Array}= &{DATA5}
36 | &{Params5}= elementData=${DATA5Array}
37 |
38 | *** Test Cases ***
39 | Channel should be launched
40 | Launch the channel ${channel_code}
41 | Verify is channel loaded ${channel_code}
42 |
43 | Check if details screen showed
44 | Send key select 4
45 | Verify is screen loaded ${Params2}
46 |
47 | Check if playback started
48 | ${status} ${value}= Run Keyword And Ignore Error Verify is screen loaded ${Params5} 2
49 | Run keyword if "${status}"=="PASS" Do auth
50 | ... ELSE Send key select
51 | Verify is playback started 10 2
52 |
53 | *** Keywords ***
54 | Do auth
55 | Send key select
56 | Verify is screen loaded ${Params3}
57 | Send word user
58 | Send keys ${KEYS}
59 | Verify is screen loaded ${Params4}
60 | Send word pass
61 | Send keys ${KEYS}
62 |
--------------------------------------------------------------------------------
/RobotLibrary/multipleDevices/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "devices": {
3 | "Austin": {
4 | "ip_address": "192.168.1.64",
5 | "timeout": 20000,
6 | "pressDelay": 2000
7 | },
8 | "Tyler": {
9 | "ip_address": "192.168.1.16",
10 | "timeout": 25000,
11 | "pressDelay": 1000
12 | }
13 | },
14 | "server_path": "D:/projects/go/webDriver/src/main.exe",
15 | "test": "multipleDevices/test_3_Grid_multi_device.robot",
16 | "outputdir": "Results"
17 | }
18 |
--------------------------------------------------------------------------------
/RobotLibrary/multipleDevices/multi.py:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2020 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | import sys
18 | import asyncio
19 | import subprocess
20 | import json
21 | from string import Template
22 | import codecs
23 | if sys.platform == "win32":
24 | asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
25 |
26 | async def read_stream(stream, cb):
27 | while True:
28 | line = await stream.readline()
29 | if line:
30 | cb(line)
31 | else:
32 | break
33 |
34 |
35 | async def stream_subprocess(cmd, stdout_cb, stderr_cb):
36 | try:
37 | process = await asyncio.create_subprocess_exec(
38 | *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
39 | )
40 |
41 | await asyncio.wait(
42 | [
43 | read_stream(process.stdout, stdout_cb),
44 | read_stream(process.stderr, stderr_cb),
45 | ]
46 | )
47 | rc = await process.wait()
48 | return process.pid, rc
49 | except OSError as e:
50 | return e
51 |
52 | async def prc(*aws):
53 | await asyncio.gather(*aws)
54 |
55 | def execute(*aws):
56 | asyncio.run(prc(*aws))
57 |
58 | def printer(label):
59 | def pr(*args):
60 | print(label, *args)
61 |
62 | return pr
63 |
64 | def runners(cmds):
65 | for cmd in cmds:
66 | out = printer(f"{cmd['name']}.stdout")
67 | err = printer(f"{cmd['name']}.stderr")
68 | yield stream_subprocess(cmd['command'], out, err)
69 |
70 | def getCmdList(config):
71 | devices = config['devices']
72 | outputdir = config['outputdir']
73 | if devices == None:
74 | raise Exception("devices field is empty")
75 |
76 | for device in devices:
77 | cmd = {
78 | 'command': [sys.executable, "-m", "robot.run"],
79 | 'name': device
80 | }
81 | deviceFields = devices[device]
82 | for key in deviceFields:
83 | cmd['command'].extend(['--variable', f'{key}:{deviceFields[key]}'])
84 | cmd['command'].extend(['--outputdir', f'{outputdir}/{device}'])
85 | cmd['command'].append(config['test'])
86 | yield cmd
87 |
88 | def createGeneralFile(config, fileName, title):
89 | devicesList = []
90 | outputdir = config['outputdir']
91 | for device in config['devices']:
92 | devicesList.append({"name": device, "src": f'{device}/{fileName}.html'})
93 | with codecs.open("multipleDevices/template.html", 'r', 'utf-8') as template:
94 | res = Template(template.read()).safe_substitute(content=devicesList, title=title)
95 | with open(f"{outputdir}/multi_device_{fileName}.html", "w") as new_file:
96 | new_file.write(res)
97 |
98 | if __name__ == "__main__":
99 | try:
100 | config_path = sys.argv[1]
101 | with open(config_path) as myfile:
102 | data = json.load(myfile)
103 | if data['server_path'] == None:
104 | raise Exception("server_path field is required")
105 | else:
106 | process = subprocess.Popen(data['server_path'])
107 | cmdList = getCmdList(data)
108 | execute(*runners(cmdList))
109 | process.kill()
110 | createGeneralFile(data, "log", "Logs")
111 | createGeneralFile(data, "report", "Reports")
112 | except IndexError:
113 | print("Config path is required as first argument")
114 | except FileNotFoundError:
115 | print('This file doesn\'t exist')
116 | except Exception as e:
117 | print(e)
118 |
--------------------------------------------------------------------------------
/RobotLibrary/multipleDevices/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
47 |
48 |
49 | $title
50 |
51 |
52 |
53 |
54 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/RobotLibrary/multipleDevices/test_3_Grid_multi_device.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2020 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 | *** Settings ***
17 | Documentation Test 2
18 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay}
19 | Library Collections
20 |
21 |
22 | *** Variables ***
23 | ${channel_code} dev
24 | &{GridData}= using=tag value=GridView
25 | @{GridArray}= &{GridData}
26 | &{GridParams}= elementData=${GridArray}
27 | &{PosterData}= using=attr attribute=name value=poster
28 | @{PosterArray}= &{PosterData}
29 | &{PosterParams}= elementData=${PosterArray}
30 | ${poster1}= https://roku-blog.s3.amazonaws.com/developer/files/2017/04/Roku-Recommends-thumbnail.png
31 | ${poster2}= https://blog.roku.com/developer/files/2016/10/twitch-poster-artwork.png
32 |
33 | *** Test Cases ***
34 | Verify is channel launched
35 | Launch the channel ${channel_code}
36 | Verify is channel loaded ${channel_code}
37 |
38 | Verify is initial screen loaded
39 | Verify is screen loaded ${GridParams}
40 |
41 | Verify posters
42 | @{elements}= Get elements ${PosterParams} 4
43 | ${realPoster1}= Get attribute ${elements[0]} uri
44 | Run Keyword If "${realPoster1}" != "${poster1}" Fail
45 | ${realPoster2}= Get attribute ${elements[1]} uri
46 | Run Keyword If "${realPoster2}" != "${poster2}" Fail
--------------------------------------------------------------------------------
/RobotLibrary/requirements.txt:
--------------------------------------------------------------------------------
1 | # Robot framework
2 | robotframework==3.1.2
3 |
4 | # Roku WebDriver API calls
5 | requests==2.22.0
6 |
--------------------------------------------------------------------------------
/RobotLibrary/setup.py:
--------------------------------------------------------------------------------
1 | import setuptools
2 |
3 | setuptools.setup(
4 | name="RokuRobotLibrary",
5 | version="2.2.0",
6 | packages=['Library'],
7 | install_requires=[
8 | 'robotframework==3.1.2',
9 | 'requests==2.22.0'
10 | ]
11 | )
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_1.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2020 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 |
27 | *** Test Cases ***
28 | Just launch the channel
29 | Launch the channel ${channel_code}
30 |
31 |
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_10.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 | @{keys} Right Select
27 | &{Grid}= using=tag value=GridView
28 | @{GridArray}= &{Grid}
29 | &{GridParams}= elementData=${GridArray}
30 | ${Title}= Roku Recommends
31 | &{DetailsData}= using=tag value=DetailsView
32 | @{DetailsArray}= &{DetailsData}
33 | &{DetailsParam}= elementData=@{DetailsArray}
34 | &{TextData}= using=text value=The Paula Deen Channel
35 | @{TextArray}= &{TextData}
36 | &{TextParam}= elementData=@{TextArray}
37 | ${validColor}= "#ddddddff"
38 | &{AdData}= using=text value=Ad 1 of 1
39 | @{AdArray}= &{AdData}
40 | &{AdParam}= elementData=@{AdArray}
41 | &{LabelData}= using=tag value=LabelList
42 | &{PlayData}= using=text value=Play
43 | @{PlayArray}= &{PlayData}
44 | @{LabelArray}= &{LabelData}
45 | &{PlayParam}= elementData=@{PlayArray} parentData=@{LabelArray}
46 |
47 | *** Test Cases ***
48 | launch the channel and verify
49 | Launch the channel ${channel_code}
50 | Verify is channel loaded ${channel_code}
51 |
52 | Verify is initial screen loaded
53 | Verify is screen loaded ${GridParams}
54 |
55 | Get info about current channel and verify Title
56 | &{app}= Get current channel info
57 | Run Keyword If "${Title}" != "${app['Title']}" Fail
58 |
59 | Open details screen
60 | Send keys ${keys} 3
61 | Verify is screen loaded ${DetailsParam}
62 |
63 | Get description element and verify color
64 | &{descriptionElement}= Get element ${TextParam}
65 | ${color}= Get attribute ${descriptionElement} color
66 | Run Keyword If "${validColor}"!="${color}" Fail
67 |
68 | Verify is Ad playback started
69 | Send key Select
70 | Verify is playback started 20 3
71 | Verify is screen loaded ${AdParam}
72 |
73 | Verify is correct Details screen opened after Back key
74 | Send key Back 3
75 | Verify is screen loaded ${PlayParam}
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_11.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 | @{keys} Right Select
27 | &{Grid}= using=tag value=GridView
28 | @{GridArray}= &{Grid}
29 | &{GridParams}= elementData=${GridArray}
30 | ${Title}= Roku Recommends
31 | &{DetailsData}= using=tag value=DetailsView
32 | @{DetailsArray}= &{DetailsData}
33 | &{DetailsParam}= elementData=@{DetailsArray}
34 | &{TextData}= using=text value=The Paula Deen Channel
35 | @{TextArray}= &{TextData}
36 | &{TextParam}= elementData=@{TextArray}
37 | ${validColor}= "#ddddddff"
38 | &{AdData}= using=text value=Ad 1 of 1
39 | @{AdArray}= &{AdData}
40 | &{AdParam}= elementData=@{AdArray}
41 | &{LabelData}= using=tag value=LabelList
42 | &{PlayData}= using=text value=Play
43 | @{PlayArray}= &{PlayData}
44 | @{LabelArray}= &{LabelData}
45 | &{PlayParam}= elementData=@{PlayArray} parentData=@{LabelArray}
46 | ${content_id}= decbe34b64ea4ca281dc09997d0f23fd
47 | ${mediaType}= episode
48 |
49 | *** Test Cases ***
50 | launch the channel and verify
51 | Launch the channel ${channel_code}
52 | Verify is channel loaded ${channel_code}
53 |
54 | Verify is initial screen loaded
55 | Verify is screen loaded ${GridParams}
56 |
57 | Get info about current channel and verify Title
58 | &{app}= Get current channel info
59 | Run Keyword If "${Title}" != "${app['Title']}" Fail
60 |
61 | Open details screen
62 | Send keys ${keys} 3
63 | Verify is screen loaded ${DetailsParam}
64 |
65 | Get description element and verify color
66 | &{descriptionElement}= Get element ${TextParam}
67 | ${color}= Get attribute ${descriptionElement} color
68 | Run Keyword If "${validColor}"!="${color}" Fail
69 |
70 | Verify is Ad playback started
71 | Send key Select
72 | Verify is playback started 20 3
73 | Verify is screen loaded ${AdParam}
74 |
75 | Verify is correct Details screen opened after Back key
76 | Send key Back 3
77 | Verify is screen loaded ${PlayParam}
78 |
79 | Verify deep linking
80 | Launch the channel ${channel_code} ${content_id} ${mediaType}
81 | Verify is channel loaded ${channel_code}
82 | Verify is playback started 20 3
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_12.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 | @{keys} Right Select
27 | &{Grid}= using=tag value=GridView
28 | @{GridArray}= &{Grid}
29 | &{GridParams}= elementData=${GridArray}
30 | ${Title}= Roku Recommends
31 | &{DetailsData}= using=tag value=DetailsView
32 | @{DetailsArray}= &{DetailsData}
33 | &{DetailsParam}= elementData=@{DetailsArray}
34 | &{TextData}= using=text value=The Paula Deen Channel
35 | @{TextArray}= &{TextData}
36 | &{TextParam}= elementData=@{TextArray}
37 | ${validColor}= "#ddddddff"
38 | &{AdData}= using=text value=Ad 1 of 1
39 | @{AdArray}= &{AdData}
40 | &{AdParam}= elementData=@{AdArray}
41 | &{LabelData}= using=tag value=LabelList
42 | &{PlayData}= using=text value=Play
43 | @{PlayArray}= &{PlayData}
44 | @{LabelArray}= &{LabelData}
45 | &{PlayParam}= elementData=@{PlayArray} parentData=@{LabelArray}
46 | ${content_id}= decbe34b64ea4ca281dc09997d0f23fd
47 | ${mediaType}= episode
48 |
49 | *** Test Cases ***
50 | launch the channel and verify
51 | Launch the channel ${channel_code}
52 | Verify is channel loaded ${channel_code}
53 |
54 | Verify is initial screen loaded
55 | Verify is screen loaded ${GridParams}
56 |
57 | Get info about current channel and verify Title
58 | &{app}= Get current channel info
59 | Run Keyword If "${Title}" != "${app['Title']}" Fail
60 |
61 | Open details screen
62 | Send keys ${keys} 3
63 | Verify is screen loaded ${DetailsParam}
64 |
65 | Get description element and verify color
66 | &{descriptionElement}= Get element ${TextParam}
67 | ${color}= Get attribute ${descriptionElement} color
68 | Run Keyword If "${validColor}"!="${color}" Fail
69 |
70 | Verify is Ad playback started
71 | Send key Select
72 | Verify is playback started 20 3
73 | Verify is screen loaded ${AdParam}
74 |
75 | Verify is correct Details screen opened after Back key
76 | Send key Back 3
77 | Verify is screen loaded ${PlayParam}
78 |
79 | Verify deep linking
80 | Mark timer
81 | Launch the channel ${channel_code} ${content_id} ${mediaType}
82 | Verify is channel loaded ${channel_code}
83 | Verify is playback started 20 3
84 |
85 | Verify launch time
86 | ${time_in}= Get timer
87 | Run Keyword If ${time_in} > 40000 Fail
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_13.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 | @{keys} Right Select
27 | &{Grid}= using=tag value=GridView
28 | @{GridArray}= &{Grid}
29 | &{GridParams}= elementData=${GridArray}
30 | ${Title}= Roku Recommends
31 | &{DetailsData}= using=tag value=DetailsView
32 | @{DetailsArray}= &{DetailsData}
33 | &{DetailsParam}= elementData=@{DetailsArray}
34 | &{TextData}= using=text value=The Paula Deen Channel
35 | @{TextArray}= &{TextData}
36 | &{TextParam}= elementData=@{TextArray}
37 | ${validColor}= "#ddddddff"
38 | &{AdData}= using=text value=Ad 1 of 1
39 | @{AdArray}= &{AdData}
40 | &{AdParam}= elementData=@{AdArray}
41 | &{LabelData}= using=tag value=LabelList
42 | &{PlayData}= using=text value=Play
43 | @{PlayArray}= &{PlayData}
44 | @{LabelArray}= &{LabelData}
45 | &{PlayParam}= elementData=@{PlayArray} parentData=@{LabelArray}
46 | ${content_id}= decbe34b64ea4ca281dc09997d0f23fd
47 | ${mediaType}= episode
48 |
49 | *** Test Cases ***
50 | launch the channel and verify
51 | Launch the channel ${channel_code}
52 | Verify is channel loaded ${channel_code}
53 |
54 | Verify is initial screen loaded
55 | Verify is screen loaded ${GridParams}
56 |
57 | Get info about current channel and verify Title
58 | &{app}= Get current channel info
59 | Run Keyword If "${Title}" != "${app['Title']}" Fail
60 |
61 | Open details screen
62 | Send keys ${keys} 3
63 | Verify is screen loaded ${DetailsParam}
64 |
65 | Get description element and verify color
66 | &{descriptionElement}= Get element ${TextParam}
67 | ${color}= Get attribute ${descriptionElement} color
68 | Run Keyword If "${validColor}"!="${color}" Fail
69 |
70 | Verify is Ad playback started
71 | Send key Select
72 | Verify is playback started 20 3
73 | Verify is screen loaded ${AdParam}
74 |
75 | Verify is correct Details screen opened after Back key
76 | Send key Back 3
77 | Verify is screen loaded ${PlayParam}
78 |
79 | Verify deep linking
80 | Mark timer
81 | Launch the channel ${channel_code} ${content_id} ${mediaType}
82 | Verify is channel loaded ${channel_code}
83 | Verify is playback started 20 3
84 |
85 | Verify launch time
86 | ${time_in}= Get timer
87 | Run Keyword If ${time_in} > 40000 Fail
88 |
89 | Verify input deep linking
90 | Send key Back 3
91 | Sleep 2
92 | Input deep linking data ${channel_code} ${content_id} ${mediaType}
93 | Verify is playback started 20 3
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_2.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2020 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 |
27 | *** Test Cases ***
28 | Just launch the channel
29 | Launch the channel ${channel_code}
30 | Verify is channel loaded ${channel_code}
31 |
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_3.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2020 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 | ${key} Down
27 |
28 | *** Test Cases ***
29 | launch the channel and verify
30 | Launch the channel ${channel_code}
31 | Verify is channel loaded ${channel_code}
32 |
33 | Simulate key press
34 | Send key ${key}
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_4.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2020 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 | @{keys} Down Down Right
27 |
28 | *** Test Cases ***
29 | launch the channel and verify
30 | Launch the channel ${channel_code}
31 | Verify is channel loaded ${channel_code}
32 |
33 | Simulate key presses
34 | Send keys ${keys}
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_5.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2020 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 | @{keys} Down Down Right
27 | &{Grid}= using=tag value=GridView
28 | @{GridArray}= &{Grid}
29 | &{GridParams}= elementData=${GridArray}
30 |
31 | *** Test Cases ***
32 | launch the channel and verify
33 | Launch the channel ${channel_code}
34 | Verify is channel loaded ${channel_code}
35 |
36 | Verify is initial screen loaded
37 | Verify is screen loaded ${GridParams}
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_6.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2020 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 | @{keys} Down Down Right
27 | &{Grid}= using=tag value=GridView
28 | @{GridArray}= &{Grid}
29 | &{GridParams}= elementData=${GridArray}
30 | ${Title}= Roku Recommends
31 | *** Test Cases ***
32 | launch the channel and verify
33 | Launch the channel ${channel_code}
34 | Verify is channel loaded ${channel_code}
35 |
36 | Verify is initial screen loaded
37 | Verify is screen loaded ${GridParams}
38 |
39 | Get info about current channel and verify Title
40 | &{app}= Get current channel info
41 | Run Keyword If "${Title}" != "${app['Title']}" Fail
42 |
43 |
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_7.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2020 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 | @{keys} Right Select
27 | &{Grid}= using=tag value=GridView
28 | @{GridArray}= &{Grid}
29 | &{GridParams}= elementData=${GridArray}
30 | ${Title}= Roku Recommends
31 | &{DetailsData}= using=tag value=DetailsView
32 | @{DetailsArray}= &{DetailsData}
33 | &{DetailsParams}= elementData=@{DetailsArray}
34 |
35 | *** Test Cases ***
36 | launch the channel and verify
37 | Launch the channel ${channel_code}
38 | Verify is channel loaded ${channel_code}
39 |
40 | Verify is initial screen loaded
41 | Verify is screen loaded ${GridParams}
42 |
43 | Get info about current channel and verify Title
44 | &{app}= Get current channel info
45 | Run Keyword If "${Title}" != "${app['Title']}" Fail
46 |
47 | Open details screen
48 | Send keys ${keys}
49 | Verify is screen loaded ${DetailsParams}
50 |
51 |
52 |
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_8.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2020 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 | @{keys} Right Select
27 | &{Grid}= using=tag value=GridView
28 | @{GridArray}= &{Grid}
29 | &{GridParams}= elementData=${GridArray}
30 | ${Title}= Roku Recommends
31 | &{DetailsData}= using=tag value=DetailsView
32 | @{DetailsArray}= &{DetailsData}
33 | &{DetailsParam}= elementData=@{DetailsArray}
34 | &{TextData}= using=text value=The Paula Deen Channel
35 | @{TextArray}= &{TextData}
36 | &{TextParam}= elementData=@{TextArray}
37 | ${validColor}= "#ddddddff"
38 |
39 | *** Test Cases ***
40 | launch the channel and verify
41 | Launch the channel ${channel_code}
42 | Verify is channel loaded ${channel_code}
43 |
44 | Verify is initial screen loaded
45 | Verify is screen loaded ${GridParams}
46 |
47 | Get info about current channel and verify Title
48 | &{app}= Get current channel info
49 | Run Keyword If "${Title}" != "${app['Title']}" Fail
50 |
51 | Open details screen
52 | Send keys ${keys}
53 | Verify is screen loaded ${DetailsParam}
54 |
55 | Get description element and verify color
56 | &{descriptionElement}= Get element ${TextParam}
57 | ${color}= Get attribute ${descriptionElement} color
58 | Run Keyword If "${validColor}"!="${color}" Fail
59 |
--------------------------------------------------------------------------------
/RobotLibrary/tutorialTests/step_9.robot:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | *** Settings ***
18 | Documentation Test 2
19 | Variables ./../Library/variables.py
20 | Library ./../Library/RobotLibrary.py ${ip_address} ${timeout} ${pressDelay} ${server_path}
21 | Library Collections
22 |
23 |
24 | *** Variables ***
25 | ${channel_code} dev
26 | @{keys} Right Select
27 | &{Grid}= using=tag value=GridView
28 | @{GridArray}= &{Grid}
29 | &{GridParams}= elementData=${GridArray}
30 | ${Title}= Roku Recommends
31 | &{DetailsData}= using=tag value=DetailsView
32 | @{DetailsArray}= &{DetailsData}
33 | &{DetailsParam}= elementData=@{DetailsArray}
34 | &{TextData}= using=text value=The Paula Deen Channel
35 | @{TextArray}= &{TextData}
36 | &{TextParam}= elementData=@{TextArray}
37 | ${validColor}= "#ddddddff"
38 | &{AdData}= using=text value=Ad 1 of 1
39 | @{AdArray}= &{AdData}
40 | &{AdParam}= elementData=@{AdArray}
41 |
42 | *** Test Cases ***
43 | launch the channel and verify
44 | Launch the channel ${channel_code}
45 | Verify is channel loaded ${channel_code}
46 |
47 | Verify is initial screen loaded
48 | Verify is screen loaded ${GridParams}
49 |
50 | Get info about current channel and verify Title
51 | &{app}= Get current channel info
52 | Run Keyword If "${Title}" != "${app['Title']}" Fail
53 |
54 | Open details screen
55 | Send keys ${keys} 3
56 | Verify is screen loaded ${DetailsParam}
57 |
58 | Get description element and verify color
59 | &{descriptionElement}= Get element ${TextParam}
60 | ${color}= Get attribute ${descriptionElement} color
61 | Run Keyword If "${validColor}"!="${color}" Fail
62 |
63 | Verify is Ad playback started
64 | Send key Select
65 | Verify is playback started 20 3
66 | Verify is screen loaded ${AdParam}
--------------------------------------------------------------------------------
/RobotLibrary/uTest/_init_.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/RobotLibrary/uTest/_init_.py
--------------------------------------------------------------------------------
/RobotLibrary/uTest/response_mock.py:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | resp = {
18 | "sessionId": "test",
19 | "status": 0,
20 | "value": {
21 | "ip": "1.1.0.127"
22 | }
23 | }
24 |
25 | respWithEmptyValue = {
26 | "sessionId": "test",
27 | "status": 0,
28 | "value": None
29 | }
30 |
31 | respWithApps = {
32 | "sessionId": "test",
33 | "status": 0,
34 | "value": [{
35 | "Title": "TestChannel",
36 | "ID": "id",
37 | "Type": "menu",
38 | "Version": "1.0.0",
39 | "Subtype": ""
40 |
41 | }]
42 | }
43 |
44 | respWithApp = {
45 | "sessionId": "test",
46 | "status": 0,
47 | "value": {
48 | "Title": "TestChannel",
49 | "ID": "id",
50 | "Type": "menu",
51 | "Version": "1.0.0",
52 | "Subtype": ""
53 |
54 | }
55 | }
56 |
57 | respWithPlayerInfo = {
58 | "sessionId": "42ff6f0d-2362-5e26-a0c9-800e3390bae0",
59 | "status": 0,
60 | "value": {
61 | "Error": "false",
62 | "State": "play",
63 | "Format": {
64 | "Audio": "",
65 | "Captions": "",
66 | "Container": "",
67 | "Drm": "",
68 | "Video": "",
69 | "VideoRes": ""
70 | },
71 | "Buffering": {
72 | "Current": "",
73 | "Max": "",
74 | "Target": ""
75 | },
76 | "NewStream": {
77 | "Speed": ""
78 | },
79 | "Position": "1000 ms",
80 | "Duration": "20000 ms",
81 | "IsLive": "",
82 | "Runtime": "",
83 | "StreamSegment": {
84 | "Bitrate": "",
85 | "MediaSequence": "",
86 | "SegmentType": "",
87 | "Time": ""
88 | }
89 | }
90 | }
91 |
92 | resultPlayerInfo = {
93 | "sessionId": "42ff6f0d-2362-5e26-a0c9-800e3390bae0",
94 | "status": 0,
95 | "value": {
96 | "Error": "false",
97 | "State": "play",
98 | "Format": {
99 | "Audio": "",
100 | "Captions": "",
101 | "Container": "",
102 | "Drm": "",
103 | "Video": "",
104 | "VideoRes": ""
105 | },
106 | "Buffering": {
107 | "Current": "",
108 | "Max": "",
109 | "Target": ""
110 | },
111 | "NewStream": {
112 | "Speed": ""
113 | },
114 | "Position": 1000,
115 | "Duration": 20000,
116 | "IsLive": "",
117 | "Runtime": "",
118 | "StreamSegment": {
119 | "Bitrate": "",
120 | "MediaSequence": "",
121 | "SegmentType": "",
122 | "Time": ""
123 | }
124 | }
125 | }
126 |
127 | uiElement = {
128 | "XMLName": {
129 | "Space": "",
130 | "Local": "Label"
131 | },
132 | "Attrs": [
133 | {
134 | "Name": {
135 | "Space": "",
136 | "Local": "bounds"
137 | },
138 | "Value": "{1, 1, 1, 1}"
139 | },
140 | {
141 | "Name": {
142 | "Space": "",
143 | "Local": "color"
144 | },
145 | "Value": "#ffffff6f"
146 | },
147 | {
148 | "Name": {
149 | "Space": "",
150 | "Local": "index"
151 | },
152 | "Value": "0"
153 | },
154 | {
155 | "Name": {
156 | "Space": "",
157 | "Local": "text"
158 | },
159 | "Value": "text"
160 | }
161 | ],
162 | "Nodes": None
163 | }
164 |
165 | respWithElement = {
166 | "sessionId": "test",
167 | "status": 0,
168 | "value": uiElement
169 | }
170 |
171 | respWithElements = {
172 | "sessionId": "test",
173 | "status": 0,
174 | "value":[uiElement]
175 | }
176 |
177 | respWithDeviceInfo = {
178 | "sessionId": "test",
179 | "status": 0,
180 | "value": {
181 | "ip": "1.1.0.127",
182 | "vendorName": "Roku",
183 | "modelName": "Roku",
184 | "language": "en",
185 | "country": "US"
186 | }
187 | }
188 |
189 | respWithSource = {
190 | "sessionId": "test",
191 | "status": 0,
192 | "value": "dfverv5vrevrf=="
193 | }
194 |
195 | errorMessage = "Error occurs"
196 |
197 | responseWithError = {
198 | "sessionId": "test",
199 | "status": 8,
200 | "value": {
201 | "message": errorMessage
202 | }
203 | }
--------------------------------------------------------------------------------
/bin/RokuWebDriver_linux:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/bin/RokuWebDriver_linux
--------------------------------------------------------------------------------
/bin/RokuWebDriver_mac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/bin/RokuWebDriver_mac
--------------------------------------------------------------------------------
/bin/RokuWebDriver_win.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/bin/RokuWebDriver_win.exe
--------------------------------------------------------------------------------
/channels/3_Grid.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/channels/3_Grid.zip
--------------------------------------------------------------------------------
/channels/4_DetailsScreen.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/channels/4_DetailsScreen.zip
--------------------------------------------------------------------------------
/channels/6_Endcards.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/channels/6_Endcards.zip
--------------------------------------------------------------------------------
/channels/7_EpisodePickerScreen.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/channels/7_EpisodePickerScreen.zip
--------------------------------------------------------------------------------
/channels/9_Bookmarks.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/channels/9_Bookmarks.zip
--------------------------------------------------------------------------------
/channels/ParagraphView.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/channels/ParagraphView.zip
--------------------------------------------------------------------------------
/channels/Roku_Recommends.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/channels/Roku_Recommends.zip
--------------------------------------------------------------------------------
/channels/SearchView.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/channels/SearchView.zip
--------------------------------------------------------------------------------
/channels/TimeGridView.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/channels/TimeGridView.zip
--------------------------------------------------------------------------------
/channels/audio_mode.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/channels/audio_mode.zip
--------------------------------------------------------------------------------
/channels/video_preloading.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/channels/video_preloading.zip
--------------------------------------------------------------------------------
/jsLibrary/library/client.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const axios = require('axios')
17 | const BASE_URL = "http://localhost:9000/v1/session"
18 |
19 |
20 | class Client {
21 |
22 | constructor(ip, timeout, delay) {
23 | this.ip = ip;
24 | this.timeout = timeout;
25 | this.delay = delay;
26 | this.sessionId = "";
27 | }
28 |
29 | async createSession(ip, timeout, delay) {
30 | return await this.doRequest('', 'post', {'ip' : ip, 'timeout': timeout, 'pressDelay': delay}, {}, false);
31 | }
32 |
33 | async launch(channel_code, contentID, contentType) {
34 | return await this.doRequest('/launch', 'post', {'channelId' : channel_code, 'contentId': contentID, 'contentType': contentType});
35 | }
36 |
37 | async sendKeypress(key) {
38 | return await this.doRequest('/press', 'post', {'Button' : key});
39 | }
40 |
41 | async deleteSession() {
42 | return await this.doRequest('', 'delete');
43 | }
44 |
45 | async getDeviceInfo() {
46 | return await this.doRequest('', 'get');
47 | }
48 |
49 | async getApps() {
50 | return await this.doRequest('/apps', 'get');
51 | }
52 |
53 | async getCurrentApp() {
54 | return await this.doRequest('/current_app', 'get');
55 | }
56 |
57 | async sendSequence(sequence) {
58 | return await this.doRequest('/press', 'post', {'button_sequence' : sequence});
59 | }
60 |
61 | async sendInputData(channelId, contentID, mediaType) {
62 | return await this.doRequest('/input', 'post', {'channelId': channelId, 'contentId' : contentID, 'contentType': mediaType });
63 | }
64 |
65 | async getPlayerInfo() {
66 | return await this.doRequest('/player', 'get');
67 | }
68 |
69 | async getScreenSource() {
70 | return await this.doRequest('/source', 'get');
71 | }
72 |
73 | async getActiveElement() {
74 | return await this.doRequest('/element/active', 'post');
75 | }
76 |
77 | async setTimeouts( timeoutType, delay) {
78 | return await this.doRequest('/timeouts', 'post', {'type': timeoutType, 'ms': delay});
79 | }
80 |
81 | async sendInstallChannel(channelCode) {
82 | return await this.doRequest('/install', 'post', {'channelId' : channelCode});
83 | }
84 |
85 | async getUiElements(data) {
86 | return await this.doRequest('/elements', 'post', data);
87 | }
88 |
89 | async getUiElement(data) {
90 | return await this.doRequest('/element', 'post', data);
91 | }
92 |
93 | async sideLoadChannel(form) {
94 | console.log
95 | return await this.doRequest('/load', 'post', form, form.getHeaders());
96 | }
97 |
98 | async addSessionId(url) {
99 | if (this.sessionId == '') {
100 | let result = await this.createSession(this.ip, this.timeout, this.delay);
101 | if (result.status == 200) {
102 | this.sessionId = result.data.sessionId;
103 | }
104 | }
105 | url = `/${this.sessionId}${url}`;
106 | return url;
107 | }
108 |
109 | async doRequest(url, method, body = {}, headers = {}, addSessionId = true) {
110 | try {
111 | if (addSessionId == true) {
112 | url = await this.addSessionId(url);
113 | }
114 | const result = await axios({
115 | method: method,
116 | url: `${BASE_URL}${url}`,
117 | data: body,
118 | headers: {
119 | ...headers
120 | }
121 | });
122 | return result;
123 | } catch (errorResponse) {
124 | const response = errorResponse.response;
125 | if (response == undefined) {
126 | throw new Error('Could not get any response');
127 | }
128 | const status = response.status;
129 | let errorMessage;
130 | if (status == 400) {
131 | errorMessage = response.data;
132 | } else {
133 | errorMessage = response.data.value.message;
134 | }
135 | throw new Error(errorMessage);
136 | }
137 | }
138 | }
139 |
140 | module.exports.Client = Client
--------------------------------------------------------------------------------
/jsLibrary/multipleDevices/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "devices": {
3 | "Austin": {
4 | "ip_address": "192.168.1.64",
5 | "timeout": 20000,
6 | "pressDelay": 2000
7 | },
8 | "Austin2": {
9 | "ip_address": "192.168.1.195",
10 | "timeout": 20000,
11 | "pressDelay": 2000
12 | }
13 | },
14 | "server_path": "D:/projects/go/webDriver/src/main.exe",
15 | "test": "D:/projects/go/webDriver/jsLibrary/multipleDevices/multiple_devices_test_basics.js",
16 | "outputdir": "Results"
17 | }
18 |
--------------------------------------------------------------------------------
/jsLibrary/multipleDevices/multi.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const { spawn } = require('child_process');
17 | const fs = require("fs");
18 |
19 | function getCmdList(config) {
20 | const devices = config.devices;
21 | if (devices === undefined) {
22 | throw new Error("devices field is empty");
23 | }
24 | let cmds = [];
25 | for(const device in devices) {
26 | let deviceFields = devices[device];
27 | let cmd = {
28 | options: '',
29 | name: device
30 | }
31 | for(const field in deviceFields) {
32 | cmd.options += `--${field}=${deviceFields[field]} `;
33 | }
34 | cmds.push(cmd);
35 | }
36 | return cmds;
37 | }
38 |
39 | function startTest(cmds, config) {
40 | let numberOfProcess = cmds.length;
41 | const {test, outputdir, server_path} = config;
42 | const webDriver = spawn(server_path);
43 | const isWin = process.platform === "win32";
44 | const executeCmd = isWin ? 'mocha.cmd' : 'mocha';
45 | cmds.forEach(({options, name}) => {
46 | let child = spawn(executeCmd, [`${test}`,'--reporter', 'mochawesome', '--reporter-options', `reportDir=${outputdir},reportFilename=${name}`, options]);
47 | child.on('error', (messasge) => {
48 | console.log(`${name} error: ${messasge}`);
49 | });
50 | child.stdout.on('data', (data) => {
51 | console.log(`${name} stdout:\n${data}`);
52 | });
53 |
54 | child.on('exit', () => {
55 | numberOfProcess--;
56 | if (numberOfProcess === 0) {
57 | webDriver.kill();
58 | createGeneralReport(config);
59 | }
60 | });
61 | });
62 | }
63 |
64 | function createGeneralReport(config) {
65 | let deviceList = [];
66 | const {devices, outputdir} = config;
67 | for(const device in devices) {
68 | deviceList.push({'name': device, 'src': `${device}.html`});
69 | }
70 | let template = fs.readFileSync('multipleDevices/template.html', 'utf8');
71 | template = template.replace('$content', JSON.stringify(deviceList));
72 | template = template.replace('$title', 'Report');
73 | fs.writeFile(`${outputdir}/multi_device_report.html`, template, (err) => {
74 | if (err) throw err;
75 | console.log(`Multi-device report saved to ${outputdir}/multi_device_report.html`);
76 | });
77 | }
78 |
79 | function checkRequiredFields(json) {
80 | const fields = ['devices', 'server_path', 'outputdir', 'test'];
81 | fields.forEach( field => {
82 | if (json[field] === undefined) {
83 | throw new Error(`Please, add field \'${field}\' to config`);
84 | }
85 | });
86 | }
87 |
88 | try {
89 | const args = process.argv;
90 | const configPath = args[2];
91 | if (configPath === undefined) {
92 | throw new Error('Path to config is required');
93 | }
94 | const config = fs.readFileSync(configPath);
95 | const jsonData = JSON.parse(config);
96 | checkRequiredFields(jsonData);
97 | const cmdList = getCmdList(jsonData);
98 | startTest(cmdList, jsonData);
99 | } catch (e) {
100 | console.log(e);
101 | }
--------------------------------------------------------------------------------
/jsLibrary/multipleDevices/multiple_devices_test_3-Grid.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const {getArgs} = require('./utils');
19 | let library;
20 | const args = getArgs();
21 | let ip = args.ip_address || "192.168.1.12";
22 | describe('Channel should be launched', () => {
23 | before(() => {
24 | library = new rokuLibrary.Library(ip);
25 | });
26 |
27 | it('should launch the channel', async function() {
28 | this.timeout(25000);
29 | await library.launchTheChannel('dev');
30 | await library.verifyIsChannelLoaded('dev');
31 | });
32 |
33 | it('Verify is initial screen loaded', async function() {
34 | this.timeout(10000);
35 | const res = await library.verifyIsScreenLoaded({
36 | 'elementData': [{'using': 'tag', 'value': 'GridView'}
37 | ]});
38 | expect(res).to.equal(true);
39 | });
40 |
41 | it('Verify posters', async function() {
42 | this.timeout(50000);
43 | const elements = await library.getElements({'elementData': [{'using': 'attr', 'attribute': 'name', 'value': 'poster'}]}, 4);
44 | let poster = library.getAttribute(elements[0], 'uri');
45 | expect(poster).to.equal('https://roku-blog.s3.amazonaws.com/developer/files/2017/04/Roku-Recommends-thumbnail.png');
46 | poster = library.getAttribute(elements[1], 'uri');
47 | expect(poster).to.equal('https://blog.roku.com/developer/files/2016/10/twitch-poster-artwork.png');
48 | });
49 |
50 | after(async () => {
51 | await library.close();
52 | });
53 | });
54 |
55 |
--------------------------------------------------------------------------------
/jsLibrary/multipleDevices/multiple_devices_test_basics.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const {getArgs} = require('./utils');
19 |
20 | let library;
21 | const args = getArgs();
22 | let ip = args.ip_address || "192.168.1.64";
23 | let timeout = parseInt(args.timeout) || 20000;
24 | let pressDelay = parseInt(args.pressDelay) || 2000;
25 | console.log(args)
26 | describe('Channel should be launched', () => {
27 | before(() => {
28 | library = new rokuLibrary.Library(ip, timeout, pressDelay);
29 | });
30 |
31 | it('should launch the channel', async function() {
32 | this.timeout(15000);
33 | await library.launchTheChannel('dev');
34 | await library.verifyIsChannelLoaded('dev');
35 | });
36 |
37 | it('Check if details screen showed', async function() {
38 | this.timeout(30000);
39 | await library.sendKey('select', 4);
40 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'text', 'value': 'Barack Gates, Bill Obama'}]});
41 | expect(res).to.equal(true);
42 | });
43 |
44 | it('Check if playback started', async function() {
45 | this.timeout(70000);
46 | let res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'text', 'value': 'Authenticate to watch'}]}, 2, 2);
47 | if (res == true) {
48 | await library.sendKey('select');
49 | res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'text', 'value': 'Please enter your username'}]});
50 | if (res == false) {
51 | expect.fail("Can't enter user name");
52 | }
53 | await library.sendWord('user');
54 | await library.sendKeys(['down', 'down', 'down', 'down', 'select']);
55 | await library.sendWord('pass');
56 | await library.sendKeys(['down', 'down', 'down', 'down', 'select']);
57 | } else {
58 | await library.sendKey('select');
59 | }
60 | res = await library.verifyIsPlaybackStarted(25, 2);
61 | expect(res).to.equal(true);
62 | });
63 |
64 | after(async () => {
65 | await library.close();
66 | });
67 | });
68 |
69 |
--------------------------------------------------------------------------------
/jsLibrary/multipleDevices/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
47 |
48 |
49 | $title
50 |
51 |
52 |
53 |
54 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/jsLibrary/multipleDevices/utils.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | function getArgs () {
17 | const data = process.argv;
18 | let args = {};
19 | const length = data.length;
20 | const options = data[length - 1];
21 | options
22 | .split(' ')
23 | .forEach((argument) => {
24 | if (argument.slice(0,2) === '--') {
25 | const arg = argument.split('=');
26 | const argFlag = arg[0].slice(2,arg[0].length);
27 | const argValue = arg.length > 1 ? arg[1] : true;
28 | args[argFlag] = argValue;
29 | }
30 | })
31 | return args;
32 | }
33 |
34 | module.exports = {
35 | getArgs: getArgs
36 | }
--------------------------------------------------------------------------------
/jsLibrary/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "test": "mocha \"tests/test_basic.js\""
4 | },
5 | "dependencies": {
6 | "axios": "0.19.1",
7 | "chai": "4.2.0",
8 | "form-data": "3.0.0",
9 | "mocha": "7.0.1",
10 | "nock": "12.0.1"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_3-Grid.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_3-Grid', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.2.121");
27 | });
28 |
29 | it('should launch the channel', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/3_Grid.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('Verify is initial screen loaded', async function() {
36 | this.timeout(10000);
37 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'GridView'}]});
38 | expect(res).to.equal(true);
39 | });
40 |
41 | it('Verify posters', async function() {
42 | this.timeout(50000);
43 | const elements = await library.getElements({'elementData': [{'using': 'attr', 'attribute': 'name', 'value': 'poster'}]}, 4);
44 | let poster = library.getAttribute(elements[0], 'uri');
45 | expect(poster).to.equal('https://roku-blog.s3.amazonaws.com/developer/files/2017/04/Roku-Recommends-thumbnail.png');
46 | poster = library.getAttribute(elements[1], 'uri');
47 | expect(poster).to.equal('https://blog.roku.com/developer/files/2016/10/twitch-poster-artwork.png');
48 | });
49 |
50 | after(async () => {
51 | await library.close();
52 | childProcess.kill();
53 | });
54 | });
55 |
56 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_3-Grid_utils.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_3-Grid_utils', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.2.11");
27 | });
28 |
29 | it('should launch the channel', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/3_Grid.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('Verify is initial screen loaded', async function() {
36 | this.timeout(10000);
37 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'GridView'}]});
38 | expect(res).to.equal(true);
39 | });
40 |
41 | it('Verify posters', async function() {
42 | this.timeout(10000);
43 | const element = await library.getFocusedElement();
44 | const result = library.getChildNodes(element, [{"using": "tag", "value": "poster"}]);
45 | if (result.length > 0) {
46 | const uri = library.getAttribute(result[0], "uri");
47 | expect(uri).to.equal("https://roku-blog.s3.amazonaws.com/developer/files/2017/04/Roku-Recommends-thumbnail.png")
48 | } else {
49 | throw new Error('Can not find poster');
50 | }
51 | });
52 |
53 | it('Verify focused row title', async function() {
54 | this.timeout(10000);
55 | const rowList = await library.getElement({"elementData" :[{"using": "tag", "value": "ZoomRowList"}]});
56 | const searchData = [{"using": "tag", "value": "RenderableNode"}, {"using": "attr", "attribute": "focused", "value": "true"}];
57 | const result = library.getChildNodes(rowList, searchData);
58 | if (result.length > 0) {
59 | const renderableNode = result[0];
60 | const labelSearchData = [{"using": "text", "value": "series"}];
61 | const labelList = library.getChildNodes(renderableNode, labelSearchData);
62 | expect(labelList.length).to.equal(1);
63 | } else {
64 | throw new Error('Can not find focused renderable node');
65 | }
66 | });
67 |
68 | after(async () => {
69 | await library.close();
70 | childProcess.kill();
71 | });
72 | });
73 |
74 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_4-DetailsScreen.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_4-DetailsScreen', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.2.11");
27 | });
28 |
29 | it('should launch the channel', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/4_DetailsScreen.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('Verify is initial screen loaded', async function() {
36 | this.timeout(10000);
37 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'GridView'}]});
38 | expect(res).to.equal(true);
39 | });
40 |
41 | it('Verify series details screen button', async function() {
42 | this.timeout(50000);
43 | await library.sendKey('select', 3);
44 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'text', 'value': 'No Content to play'}]}, 3, 4);
45 | expect(res).equal(true);
46 | });
47 |
48 | it('Verify movies details screen button', async function() {
49 | this.timeout(50000);
50 | await library.sendKeys(['back', 'down', 'select'], 3);
51 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'text', 'value': 'Play'}]}, 3, 4);
52 | expect(res).equal(true);
53 | });
54 |
55 | after(async () => {
56 | await library.close();
57 | childProcess.kill();
58 | });
59 | });
60 |
61 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_6-Encards.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_6-Encards', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.2.11");
27 | });
28 |
29 | it('should launch the channel', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/6_Endcards.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('Verify is initial screen loaded', async function() {
36 | this.timeout(10000);
37 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'GridView'}]});
38 | expect(res).to.equal(true);
39 | });
40 |
41 | it('Verify is details screen loaded', async function() {
42 | this.timeout(50000);
43 | await library.sendKey('select', 3);
44 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'DetailsView'}]});
45 | expect(res).equal(true);
46 | });
47 |
48 | it('Verify is playback started', async function() {
49 | this.timeout(50000);
50 | await library.sendKey('select', 3);
51 | const res = await library.verifyIsPlaybackStarted();
52 | expect(res).equal(true);
53 | });
54 |
55 | it('Encards', async function() {
56 | this.timeout(80000);
57 | await library.sendKeys(['fwd', 'fwd', 'fwd', 'fwd']);
58 | await library.sendKey('select', 3);
59 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'text', 'value': 'Play'}]}, 5, 5);
60 | expect(res).equal(true);
61 | });
62 |
63 | after(async () => {
64 | await library.close();
65 | childProcess.kill();
66 | });
67 | });
68 |
69 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_7-EpisodePicker.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_7-EpisodePicker', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.2.11");
27 | });
28 |
29 | it('should launch the channel', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/7_EpisodePickerScreen.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('Verify is initial screen loaded', async function() {
36 | this.timeout(10000);
37 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'GridView'}]});
38 | expect(res).to.equal(true);
39 | });
40 |
41 | it('Verify is details screen loaded', async function() {
42 | this.timeout(50000);
43 | await library.sendKey('select', 3);
44 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'DetailsView'}]});
45 | expect(res).equal(true);
46 | });
47 |
48 | it('Verify is Categort list loaded', async function() {
49 | this.timeout(50000);
50 | await library.sendKey('select', 3);
51 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'CategoryListView'}]});
52 | expect(res).equal(true);
53 | });
54 |
55 | it('Verify is Season1 is focused', async function() {
56 | this.timeout(10000);
57 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'RenderableNode'},
58 | {'using': 'attr', 'attribute': 'focused', 'value': 'true'},
59 | {'using': 'attr', 'attribute': 'index', 'value': '0'}
60 | ]});
61 | expect(res).equal(true);
62 | });
63 |
64 | it('Verify is Season2 is focused', async function() {
65 | this.timeout(20000);
66 | await library.sendKeys(['Down', 'Down', 'Down', 'Down', 'Down', 'Down']);
67 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'RenderableNode'},
68 | {'using': 'attr', 'attribute': 'focused', 'value': 'true'},
69 | {'using': 'attr', 'attribute': 'index', 'value': '1'}
70 | ]});
71 | expect(res).equal(true);
72 | });
73 |
74 |
75 | after(async () => {
76 | await library.close();
77 | childProcess.kill();
78 | });
79 | });
80 |
81 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_7_EpisodePicker_focus.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | const getChildNodesByTag = (node, name) => {
23 | const children = node.Nodes;
24 | const result = []
25 | if (children == null) {
26 | return result
27 | }
28 | name = name.toLowerCase()
29 | children.forEach((value) => {
30 | if (value.XMLName.Local.toLowerCase() == name) {
31 | result.push(value)
32 | }
33 | const elements = getChildNodesByTag(value, name)
34 | result.push(...elements)
35 | })
36 | return result
37 | }
38 |
39 | let library;
40 |
41 | describe('test_7-EpisodePicker_focus', () => {
42 | before(async function() {
43 | this.timeout(20000);
44 | library = new rokuLibrary.Library("192.168.2.11");
45 | await library.sideLoad("../channels/7_EpisodePickerScreen.zip", "rokudev", "aaaa");
46 | });
47 |
48 | it('Check if channel exist on the device', async function() {
49 | this.timeout(5000);
50 | const apps = await library.getApps();
51 | const res = library.verifyIsChannelExist(apps, 'dev');
52 | expect(res).equal(true);
53 | });
54 |
55 | it('Verify is initial screen loaded', async function() {
56 | this.timeout(10000);
57 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'GridView'}]});
58 | expect(res).to.equal(true);
59 | });
60 |
61 | it('Verify focused element on grid screen', async function() {
62 | this.timeout(50000);
63 | await library.sendKey('down', 3);
64 | const element = await library.getFocusedElement();
65 | const children = getChildNodesByTag(element, "poster");
66 | if (children.length > 0) {
67 | const poster = children[0];
68 | const posterUri = library.getAttribute(poster, "uri");
69 | expect(posterUri).to.equal("https://blog.roku.com/developer/files/2016/10/twitch-poster-artwork.png")
70 | } else {
71 | throw new Error("Can't find poster")
72 | }
73 | });
74 |
75 | it('Verify is details screen loaded', async function() {
76 | this.timeout(50000);
77 | await library.sendKeys(['up','select'], 3);
78 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'DetailsView'}]});
79 | expect(res).equal(true);
80 | });
81 |
82 | it('Verify focused element on details screen', async function() {
83 | this.timeout(50000);
84 | const element = await library.getFocusedElement();
85 | const children = getChildNodesByTag(element, 'label');
86 | if (children.length > 0) {
87 | const label = children[0];
88 | const labelText = library.getAttribute(label, 'text');
89 | expect(labelText).to.equal("Episodes")
90 | } else {
91 | throw new Error("Can't find label")
92 | }
93 | });
94 |
95 | it('Verify is Categort list loaded', async function() {
96 | this.timeout(50000);
97 | await library.sendKey('select', 3);
98 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'CategoryListView'}]});
99 | expect(res).equal(true);
100 | });
101 |
102 | it('Verify focused element on episodes screen (episodes list)', async function() {
103 | this.timeout(50000);
104 | await library.sendKey('down');
105 | const element = await library.getFocusedElement();
106 | const children = getChildNodesByTag(element, 'label');
107 | if (children.length > 0) {
108 | const label = children[0];
109 | const labelText = library.getAttribute(label, 'text');
110 | expect(labelText).to.equal("Ideas Worth Spreading")
111 | } else {
112 | throw new Error("Can't find label")
113 | }
114 | });
115 |
116 | it('Verify focused element on episodes screen (seasons list)', async function() {
117 | this.timeout(50000);
118 | await library.sendKey('left');
119 | const element = await library.getFocusedElement();
120 | const children = getChildNodesByTag(element, 'label');
121 | if (children.length > 0) {
122 | const label = children[0];
123 | const labelText = library.getAttribute(label, 'text');
124 | expect(labelText).to.equal("Season 1")
125 | } else {
126 | throw new Error("Can't find label")
127 | }
128 | });
129 |
130 | after(async () => {
131 | await library.close();
132 | childProcess.kill();
133 | });
134 | });
135 |
136 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_9-Bookmarks.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_9-Bookmarks', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.2.11");
27 | });
28 |
29 | it('should launch the channel', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/9_Bookmarks.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('Verify is details screen loaded', async function() {
36 | this.timeout(50000);
37 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'DetailsView'}]});
38 | expect(res).equal(true);
39 | });
40 |
41 | it('Verify is playback started', async function() {
42 | this.timeout(50000);
43 | await library.sendKey('select', 3);
44 | const res = await library.verifyIsPlaybackStarted();
45 | expect(res).equal(true);
46 | });
47 |
48 | it('Bookmarks', async function() {
49 | this.timeout(50000);
50 | await library.sleep(12000);
51 | await library.sendKey('back', 3);
52 | let res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'DetailsView'}]});
53 | expect(res).equal(true);
54 | await library.sendKeys(['down', 'select'], 3);
55 | res = await library.verifyIsPlaybackStarted();
56 | expect(res).equal(true);
57 | let data = await library.getPlayerInfo();
58 | expect(data.Position).greaterThan(9000);
59 | });
60 |
61 | after(async () => {
62 | await library.close();
63 | childProcess.kill();
64 | });
65 | });
66 |
67 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_ParagraphView.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_ParagraphView', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.1.64");
27 | });
28 |
29 | it('should launch the channel', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/ParagraphView.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('Verify is initial screen loaded', async function() {
36 | this.timeout(10000);
37 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'ParagraphView'}]});
38 | expect(res).to.equal(true);
39 | });
40 |
41 | it('Verify header color', async function() {
42 | this.timeout(50000);
43 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'text', 'value': 'Header Text'}, {'using': 'attr', 'attribute': 'color', 'value': '#22ffffff'}]});
44 | expect(res).equal(true);
45 | });
46 |
47 | it('Verify reload linking code', async function() {
48 | this.timeout(50000);
49 | const params = [{'using': 'attr', 'attribute': 'index', 'value': '4'}, {'using': 'attr', 'attribute': 'color', 'value': '#ffff22ff'}];
50 | let element = await library.getElement({'elementData': params});
51 | const code = library.getAttribute(element, 'text');
52 | await library.sendKey('select');
53 | element = await library.getElement({'elementData': params});
54 | const newCode = library.getAttribute(element, 'text');
55 | expect(code).to.not.equal(newCode);
56 | });
57 |
58 | after(async () => {
59 | await library.close();
60 | childProcess.kill();
61 | });
62 | });
63 |
64 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_Roku-Recommends.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_Roku-Recommends', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.2.121");
27 | });
28 |
29 | it('should launch the channel', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/Roku_Recommends.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('Verify is initial screen loaded', async function() {
36 | this.timeout(10000);
37 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'GridView'}]});
38 | expect(res).to.equal(true);
39 | });
40 |
41 | it('Should be 3 Rows on Grid initially', async function() {
42 | this.timeout(50000);
43 | const params = [ {'using': 'tag','value': 'Row'}];
44 | const elements = await library.getElements({'elementData': params});
45 | expect(elements.length).to.equal(3);
46 | });
47 |
48 | it('Should be 4 Rows on Grid after Down key press', async function() {
49 | this.timeout(50000);
50 | await library.sendKey('down');
51 | const params = [ {'using': 'tag','value': 'Row'}];
52 | const elements = await library.getElements({'elementData': params});
53 | expect(elements.length).to.equal(4);
54 | });
55 |
56 | after(async () => {
57 | await library.close();
58 | childProcess.kill();
59 | });
60 | });
61 |
62 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_Roku-Recommends_input.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_Roku_Recommends_input', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.1.11");
27 | });
28 |
29 | it('side loading', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/Roku_Recommends.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('input deep linking', async function() {
36 | this.timeout(50000);
37 | await library.sleep(1000);
38 | await library.inputDeepLinkingData('dev', 'decbe34b64ea4ca281dc09997d0f23fd', 'episode');
39 | library.markTimer();
40 | await library.sleep(1000);
41 | let res = await library.verifyIsPlaybackStarted(25, 1);
42 | expect(res).to.equal(true);
43 | let time = library.getTimer();
44 | expect(14000).greaterThan(time);
45 | });
46 |
47 | after(async () => {
48 | await library.close();
49 | childProcess.kill();
50 | });
51 | });
52 |
53 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_Roku_Recommends_deepLinking.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_Roku_Recommends_deeplinking', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.1.11");
27 | });
28 |
29 | it('side loading', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/Roku_Recommends.zip", "rokudev", "aaaa");
32 | await library.sendKey('Home');
33 | });
34 |
35 | it('should launch the channel', async function() {
36 | this.timeout(5000);
37 | await library.launchTheChannel('dev', 'decbe34b64ea4ca281dc09997d0f23fd', 'episode');
38 | await library.verifyIsChannelLoaded('dev');
39 | });
40 |
41 | it('Verify is playback started', async function() {
42 | this.timeout(50000);
43 | const res = await library.verifyIsPlaybackStarted(20, 2);
44 | expect(res).equal(true);
45 | });
46 |
47 | after(async () => {
48 | await library.close();
49 | childProcess.kill();
50 | });
51 | });
52 |
53 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_SearchView.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_SearchView', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.1.11");
27 | });
28 |
29 | it('should launch the channel', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/SearchView.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('Verify is initial screen loaded', async function() {
36 | this.timeout(10000);
37 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'SearchView'}]});
38 | expect(res).to.equal(true);
39 | });
40 |
41 | it('Verify search input', async function() {
42 | this.timeout(50000);
43 | const input = 'hello@1 r~';
44 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'text', 'value': 'Enter search term'}]});
45 | expect(res).to.equal(true);
46 | await library.sendWord(input);
47 | const inputLabel = await library.getElement({
48 | 'elementData': [{'using': 'tag', 'value': 'Label'}],
49 | 'parentData': [{'using': 'tag', 'value': 'TextEditBox'}]
50 | });
51 | const text = library.getAttribute(inputLabel, 'text');
52 | expect(text).to.equal(input);
53 | });
54 |
55 | after(async () => {
56 | await library.close();
57 | childProcess.kill();
58 | });
59 | });
60 |
61 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_TimeGridView.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_TimeGridView', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.1.64");
27 | });
28 |
29 | it('should launch the channel', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/TimeGridView.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('Verify is initial screen loaded', async function() {
36 | this.timeout(10000);
37 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'TimeGridView'}]});
38 | expect(res).to.equal(true);
39 | });
40 |
41 | it('Verify Label text', async function() {
42 | this.timeout(10000);
43 | const element = await library.getElement(
44 | {'elementData': [{'using': 'tag', 'value': 'Label'}],
45 | 'parentData': [{'using': 'tag', 'value': 'ChannelRow'}, {'using': 'attr', 'attribute': 'index', 'value': '1'}]
46 | });
47 | const value = library.getAttribute(element, 'text');
48 | expect(value).to.equal('KTVK-SD 3.2');
49 | });
50 |
51 | after(async () => {
52 | await library.close();
53 | childProcess.kill();
54 | });
55 | });
56 |
57 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_audio-mode.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_audio-mode', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.2.11");
27 | });
28 |
29 | it('should launch the channel', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/audio_mode.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('Verify is initial screen loaded', async function() {
36 | this.timeout(10000);
37 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'GridView'}]});
38 | expect(res).to.equal(true);
39 | });
40 |
41 | it('Verify is details screen loaded', async function() {
42 | this.timeout(50000);
43 | await library.sendKey('select', 3);
44 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'DetailsView'}]});
45 | expect(res).equal(true);
46 | });
47 |
48 | it('Verify is MediaView loaded', async function() {
49 | this.timeout(50000);
50 | await library.sendKey('select', 3);
51 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'MediaView'}]});
52 | expect(res).equal(true);
53 | });
54 |
55 | it('Verify next content after FF', async function() {
56 | this.timeout(80000);
57 | await library.sendKeys(['fwd', 'fwd', 'fwd', 'fwd', 'fwd'], 3);
58 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'text', 'value': 'Item 1.2'}]}, 6, 3);
59 | expect(res).equal(true);
60 | });
61 |
62 | after(async () => {
63 | await library.close();
64 | childProcess.kill();
65 | });
66 | });
67 |
68 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_basic.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_basic', () => {
25 | before(async function() {
26 | this.timeout(50000);
27 | library = new rokuLibrary.Library("192.168.2.121");
28 | await library.sideLoad("../sample/channel.zip", "rokudev", "aaaa");
29 | });
30 |
31 | it('should launch the channel', async function() {
32 | this.timeout(15000);
33 | await library.verifyIsChannelLoaded('dev');
34 | });
35 |
36 | it('Check if details screen showed', async function() {
37 | this.timeout(30000);
38 | await library.sendKey('select', 4);
39 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'text', 'value': 'Barack Gates, Bill Obama'}]});
40 | expect(res).to.equal(true);
41 | });
42 |
43 | it('Check if playback started', async function() {
44 | this.timeout(50000);
45 | let res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'text', 'value': 'Authenticate to watch'}]}, 2, 2);
46 | if (res == true) {
47 | await library.sendKey('select');
48 | res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'text', 'value': 'Please enter your username'}]});
49 | if (res == false) {
50 | expect.fail("Can't enter user name");
51 | }
52 | await library.sendWord('user');
53 | await library.sendKeys(['down', 'down', 'down', 'down', 'select']);
54 | await library.sendWord('pass');
55 | await library.sendKeys(['down', 'down', 'down', 'down', 'select']);
56 | } else {
57 | await library.sendKey('select');
58 | }
59 | res = await library.verifyIsPlaybackStarted();
60 | expect(res).to.equal(true);
61 | });
62 |
63 | after(async () => {
64 | await library.close();
65 | childProcess.kill();
66 | });
67 | });
68 |
69 |
--------------------------------------------------------------------------------
/jsLibrary/tests/test_video-preloading.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const rokuLibrary = require("../library/rokuLibrary");
17 | const expect = require("chai").expect;
18 | const { spawn } = require('child_process');
19 |
20 | const childProcess = spawn('D:/projects/go/webDriver/src/main.exe');
21 |
22 | let library;
23 |
24 | describe('test_video-preloading', () => {
25 | before(() => {
26 | library = new rokuLibrary.Library("192.168.2.11");
27 | });
28 |
29 | it('should launch the channel', async function() {
30 | this.timeout(25000);
31 | await library.sideLoad("../channels/video_preloading.zip", "rokudev", "aaaa");
32 | await library.verifyIsChannelLoaded('dev');
33 | });
34 |
35 | it('Verify is initial screen loaded', async function() {
36 | this.timeout(10000);
37 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'GridView'}]});
38 | expect(res).to.equal(true);
39 | });
40 |
41 | it('Verify is details screen loaded', async function() {
42 | this.timeout(50000);
43 | await library.sendKey('select', 3);
44 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'DetailsView'}]});
45 | expect(res).equal(true);
46 | });
47 |
48 | it('Verify is playback started', async function() {
49 | this.timeout(50000);
50 | await library.sendKey('select', 3);
51 | const res = await library.verifyIsPlaybackStarted();
52 | expect(res).equal(true);
53 | });
54 |
55 | it('Verify endcard after first video', async function() {
56 | this.timeout(80000);
57 | const res = await library.verifyIsScreenLoaded({'elementData': [{'using': 'tag', 'value': 'EndcardView'}]}, 15, 5);
58 | expect(res).equal(true);
59 | });
60 |
61 |
62 | it('Verify is playback started after 10 seconds', async function() {
63 | this.timeout(50000);
64 | const res = await library.verifyIsPlaybackStarted(3, 5);
65 | expect(res).equal(true);
66 | });
67 |
68 | after(async () => {
69 | await library.close();
70 | childProcess.kill();
71 | });
72 | });
73 |
74 |
--------------------------------------------------------------------------------
/jsLibrary/uTest/responses.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const uiElement = {
17 | "XMLName": {
18 | "Space": "",
19 | "Local": "Label"
20 | },
21 | "Attrs": [
22 | {
23 | "Name": {
24 | "Space": "",
25 | "Local": "bounds"
26 | },
27 | "Value": "{1, 1, 1, 1}"
28 | },
29 | {
30 | "Name": {
31 | "Space": "",
32 | "Local": "color"
33 | },
34 | "Value": "#ffffff6f"
35 | },
36 | {
37 | "Name": {
38 | "Space": "",
39 | "Local": "index"
40 | },
41 | "Value": "0"
42 | },
43 | {
44 | "Name": {
45 | "Space": "",
46 | "Local": "text"
47 | },
48 | "Value": "text"
49 | }
50 | ],
51 | "Nodes": null
52 | }
53 |
54 | module.exports = {
55 | uiElement: uiElement,
56 | respWithEmptyValue: {
57 | "sessionId": "test",
58 | "status": 0,
59 | "value": null
60 | },
61 | requestLaunch: {
62 | 'channelId': /.+/i,
63 | 'contentId': '',
64 | 'contentType': ''
65 | },
66 | requestInstall: {
67 | 'channelId': /.+/i
68 | },
69 | resp: {
70 | 'sessionId': '11111',
71 | 'status': 0,
72 | 'value': {
73 | 'ip': '127.0.0.1',
74 | 'timeout': 20000,
75 | 'pressDelay': 2000
76 | }
77 | },
78 | requestPress: {
79 | 'button': /.+/i
80 | },
81 | requestSequence: {
82 | 'button_sequence': [/.+/i, /.+/i]
83 | },
84 | respWithDeviceInfo: {
85 | "sessionId": "11111",
86 | "status": 0,
87 | "value": {
88 | "ip": "1.1.0.127",
89 | "vendorName": "Roku",
90 | "modelName": "Roku",
91 | "language": "en",
92 | "country": "US"
93 | }
94 | },
95 | respWithApps: {
96 | "sessionId": "11111",
97 | "status": 0,
98 | "value": [{
99 | "Title": "TestChannel",
100 | "ID": "id",
101 | "Type": "menu",
102 | "Version": "1.0.0",
103 | "Subtype": ""
104 |
105 | }]
106 | },
107 | respWithApp: {
108 | "sessionId": "11111",
109 | "status": 0,
110 | "value": {
111 | "Title": "TestChannel",
112 | "ID": "id",
113 | "Type": "menu",
114 | "Version": "1.0.0",
115 | "Subtype": ""
116 |
117 | }
118 | },
119 | respWithPlayerInfo: {
120 | "sessionId": "11111",
121 | "status": 0,
122 | "value": {
123 | "Error": "false",
124 | "State": "play",
125 | "Format": {
126 | "Audio": "",
127 | "Captions": "",
128 | "Container": "",
129 | "Drm": "",
130 | "Video": "",
131 | "VideoRes": ""
132 | },
133 | "Buffering": {
134 | "Current": "",
135 | "Max": "",
136 | "Target": ""
137 | },
138 | "NewStream": {
139 | "Speed": ""
140 | },
141 | "Position": "1000 ms",
142 | "Duration": "20000 ms",
143 | "IsLive": "",
144 | "Runtime": "",
145 | "StreamSegment": {
146 | "Bitrate": "",
147 | "MediaSequence": "",
148 | "SegmentType": "",
149 | "Time": ""
150 | }
151 | }
152 | },
153 | respWithElement: {
154 | "sessionId": "11111",
155 | "status": 0,
156 | "value": uiElement
157 | },
158 | respWithElements: {
159 | "sessionId": "11111",
160 | "status": 0,
161 | "value":[uiElement]
162 | },
163 | requestElement: {
164 | "elementData" :[{
165 | "using": /.+/i,
166 | "value": /.+/i
167 | }]
168 | },
169 | requestTimeout: {
170 | 'type': /.+/i,
171 | 'ms': /.+/i
172 | },
173 | respWithSource: {
174 | "sessionId": "11111",
175 | "status": 0,
176 | "value": "dfverv5vrevrf=="
177 | },
178 | responseWithError: {
179 | "sessionId": "11111",
180 | "status": 8,
181 | "value": {
182 | "message": "Error"
183 | }
184 | }
185 | }
--------------------------------------------------------------------------------
/jsLibrary/uTest/test_client.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2020 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | const ecp = require("../library/client");
17 | const expect = require("chai").expect;
18 | const nock = require('nock');
19 | const {
20 | respWithEmptyValue,
21 | requestLaunch,
22 | resp,
23 | requestPress,
24 | requestInstall,
25 | requestSequence,
26 | respWithDeviceInfo,
27 | respWithApps,
28 | respWithApp,
29 | respWithPlayerInfo,
30 | respWithElement,
31 | requestElement,
32 | respWithElements,
33 | requestTimeout,
34 | respWithSource
35 | } = require('./responses')
36 | let client;
37 | const baseUrl = 'http://localhost:9000/v1/session';
38 | const sessionId = resp.sessionId;
39 |
40 | describe('client tests', () => {
41 | before(async () => {
42 | nock('http://localhost:9000/v1')
43 | .post('/session', {'ip' : '127.0.0.1', 'timeout': 20000, 'pressDelay': 2000})
44 | .reply(200, resp);
45 | client = new ecp.Client('127.0.0.1', 20000, 2000);
46 | });
47 |
48 | it('test launch', async () => {
49 | nock(baseUrl)
50 | .post(`/${sessionId}/launch`, requestLaunch)
51 | .reply(200, respWithEmptyValue);
52 | const response = await client.launch('dev', '', '');
53 | expect(JSON.stringify(respWithEmptyValue)).to.equal(JSON.stringify(response.data));
54 | });
55 |
56 | it('test sendKeypress', async () => {
57 | nock(baseUrl)
58 | .post(`/${sessionId}/press`, requestPress)
59 | .reply(200, respWithEmptyValue);
60 | const response = await client.sendKeypress('select');
61 | expect(JSON.stringify(respWithEmptyValue)).to.equal(JSON.stringify(response.data));
62 | });
63 |
64 | it('test install', async () => {
65 | nock(baseUrl)
66 | .post(`/${sessionId}/install`, requestInstall)
67 | .reply(200, respWithEmptyValue);
68 | const response = await client.sendInstallChannel('1111');
69 | expect(JSON.stringify(respWithEmptyValue)).to.equal(JSON.stringify(response.data));
70 | });
71 |
72 | it('test send sequence', async () => {
73 | nock(baseUrl)
74 | .post(`/${sessionId}/press`, requestSequence)
75 | .reply(200, respWithEmptyValue);
76 | const response = await client.sendSequence(['up', 'select']);
77 | expect(JSON.stringify(respWithEmptyValue)).to.equal(JSON.stringify(response.data));
78 | });
79 |
80 | it('test get device info', async () => {
81 | nock(baseUrl)
82 | .get(`/${sessionId}`)
83 | .reply(200, respWithDeviceInfo);
84 | const response = await client.getDeviceInfo();
85 | expect(JSON.stringify(respWithDeviceInfo)).to.equal(JSON.stringify(response.data));
86 | });
87 |
88 | it('test get apps', async () => {
89 | nock(baseUrl)
90 | .get(`/${sessionId}/apps`)
91 | .reply(200, respWithApps);
92 | const response = await client.getApps();
93 | expect(JSON.stringify(respWithApps)).to.equal(JSON.stringify(response.data));
94 | });
95 |
96 | it('test get current app', async () => {
97 | nock(baseUrl)
98 | .get(`/${sessionId}/current_app`)
99 | .reply(200, respWithApp);
100 | const response = await client.getCurrentApp();
101 | expect(JSON.stringify(respWithApp)).to.equal(JSON.stringify(response.data));
102 | });
103 |
104 | it('test get player', async () => {
105 | nock(baseUrl)
106 | .get(`/${sessionId}/player`)
107 | .reply(200, respWithPlayerInfo);
108 | const response = await client.getPlayerInfo();
109 | expect(JSON.stringify(respWithPlayerInfo)).to.equal(JSON.stringify(response.data));
110 | });
111 |
112 | it('test get ui element', async () => {
113 | nock(baseUrl)
114 | .post(`/${sessionId}/element`,requestElement)
115 | .reply(200, respWithElement);
116 | const response = await client.getUiElement({
117 | "elementData" :[{
118 | "using": "tag",
119 | "value": "Label"
120 | }]
121 | });
122 | expect(JSON.stringify(respWithElement)).to.equal(JSON.stringify(response.data));
123 | });
124 |
125 | it('test get ui elements', async () => {
126 | nock(baseUrl)
127 | .post(`/${sessionId}/elements`, requestElement)
128 | .reply(200, respWithElements);
129 | const response = await client.getUiElements({
130 | "elementData" :[{
131 | "using": "tag",
132 | "value": "Label"
133 | }]
134 | });
135 | expect(JSON.stringify(respWithElements)).to.equal(JSON.stringify(response.data));
136 | });
137 |
138 | it('test get active element', async () => {
139 | nock(baseUrl)
140 | .post(`/${sessionId}/element/active`, {})
141 | .reply(200, respWithElement);
142 | const response = await client.getActiveElement();
143 | expect(JSON.stringify(respWithElement)).to.equal(JSON.stringify(response.data));
144 | });
145 |
146 | it('test set timeouts', async () => {
147 | nock(baseUrl)
148 | .post(`/${sessionId}/timeouts`, requestTimeout)
149 | .reply(200, respWithEmptyValue);
150 | const response = await client.setTimeouts("implicit", 1000);
151 | expect(JSON.stringify(respWithEmptyValue)).to.equal(JSON.stringify(response.data));
152 | });
153 |
154 | it('test get screen source', async () => {
155 | nock(baseUrl)
156 | .get(`/${sessionId}/source`)
157 | .reply(200, respWithSource);
158 | const response = await client.getScreenSource();
159 | expect(JSON.stringify(respWithSource)).to.equal(JSON.stringify(response.data));
160 | });
161 |
162 | it('test send input data', async () => {
163 | nock(baseUrl)
164 | .post(`/${sessionId}/input`)
165 | .reply(200, respWithEmptyValue);
166 | const response = await client.sendInputData('dev', '12', 'movie');
167 | expect(JSON.stringify(respWithEmptyValue)).to.equal(JSON.stringify(response.data));
168 | });
169 |
170 | it('test deleteSession', async () => {
171 | nock(baseUrl)
172 | .delete(`/${sessionId}`)
173 | .reply(200, respWithEmptyValue);
174 | const response = await client.deleteSession();
175 | expect(JSON.stringify(respWithEmptyValue)).to.equal(JSON.stringify(response.data));
176 | });
177 | });
178 |
179 |
--------------------------------------------------------------------------------
/sample/Postman/README.txt:
--------------------------------------------------------------------------------
1 | WebDriver Postman collection
2 |
3 | 1.) Side load Roku Recommends sample channel.
4 |
5 | 2.) WebDriver_endpoints file should be imported as Postman collection.
6 |
7 | 3.) Open "create session" request and populate "ip" field in request body with your Roku Device IP adress.
8 |
9 | 4.) Start instance of Roku webDriver.
10 |
11 | 5.) Execute "create session" request to create new session.
12 |
13 | 6.) Exucute all other request.
14 |
15 | 7.) Execute "delete session" request to remove session.
16 |
17 |
18 |
--------------------------------------------------------------------------------
/sample/channel.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rokudev/automated-channel-testing/13528aefbda05ced9895ec24e9e258d02131ec82/sample/channel.zip
--------------------------------------------------------------------------------
/sample/script/main.py:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | from webDriver import WebDriver
18 | import sys
19 |
20 | def run(ip: str):
21 | try:
22 | web_driver = WebDriver(ip)
23 | web_driver.launch_the_channel("dev")
24 | web_driver.verify_is_screen_loaded({"elementData": [{
25 | "using": "text",
26 | "value": "ROW 1"
27 | }]})
28 |
29 | web_driver.press_btn("select")
30 | web_driver.verify_is_screen_loaded({"elementData": [{
31 | "using": "text",
32 | "value": "Barack Gates, Bill Obama"
33 | }]})
34 |
35 | res = web_driver.verify_is_screen_loaded({"elementData": [{
36 | "using": "text",
37 | "value": "Authenticate to watch"
38 | }]}, False, 2)
39 | if res == False:
40 | res = web_driver.verify_is_screen_loaded({"elementData": [{
41 | "using": "text",
42 | "value": "Play"
43 | }]})
44 | web_driver.press_btn("select")
45 | else:
46 | web_driver.press_btn("select")
47 | web_driver.verify_is_screen_loaded({"elementData": [{
48 | "using": "text",
49 | "value": "Please enter your username"
50 | }]})
51 | web_driver.send_word("user")
52 | web_driver.send_button_sequence(["down", "down", "down", "down", "select"])
53 | web_driver.verify_is_screen_loaded({"elementData": [{
54 | "using": "text",
55 | "value": "Please enter your password"
56 | }]})
57 | web_driver.send_word("pass")
58 | web_driver.send_button_sequence(["down", "down", "down", "down", "select"])
59 | print(f"{ip}: Test passed")
60 | except Exception as e:
61 | print(f"{ip}: Error: {e}")
62 | print(f"{ip}: Test failed")
63 | finally:
64 | web_driver.quiet()
65 |
66 | if __name__ == "__main__":
67 | run(sys.argv[1])
--------------------------------------------------------------------------------
/sample/script/multipleDeviceSample.py:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | from main import run
18 | import sys
19 | import threading
20 |
21 | if __name__ == "__main__":
22 | arguments_list = sys.argv[1:]
23 | for ip in arguments_list:
24 | thread = threading.Thread(target=run, args=(ip,))
25 | thread.start()
26 |
--------------------------------------------------------------------------------
/sample/script/webDriver.py:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Copyright 2019 Roku, Inc.
3 | #
4 | #Licensed under the Apache License, Version 2.0 (the "License");
5 | #you may not use this file except in compliance with the License.
6 | #You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | #Unless required by applicable law or agreed to in writing, software
11 | #distributed under the License is distributed on an "AS IS" BASIS,
12 | #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | #See the License for the specific language governing permissions and
14 | #limitations under the License.
15 | ########################################################################
16 |
17 | import requests
18 | import json
19 | from time import sleep
20 |
21 | class WebDriver:
22 | def __init__(self, roku_ip_address: str):
23 | data = {'ip' : roku_ip_address}
24 | request_url = self._build_request_url('')
25 | response = self._post(request_url, data)
26 | res = json.loads(response.text)
27 | self._session_id = res['sessionId']
28 |
29 | def _send_launch_channel(self, channel_code: str):
30 | data = {'channelId' : channel_code}
31 | request_url = self._build_request_url(f"/{self._session_id}/launch")
32 | return self._post(request_url, data)
33 |
34 | def _send_sequence(self, sequence):
35 | data = {'button_sequence' : sequence}
36 | request_url = self._build_request_url(f"/{self._session_id}/press")
37 | return self._post(request_url, data)
38 |
39 | def _get_ui_element(self, data: object):
40 | request_url = self._build_request_url(f"/{self._session_id}/element")
41 | return self._post(request_url, data)
42 |
43 | def _send_keypress(self, key_press: str):
44 | data = {'button' : key_press}
45 | request_url = self._build_request_url(f"/{self._session_id}/press")
46 | return self._post(request_url, data)
47 |
48 | def _build_request_url(self, endpoint: str):
49 | return f"http://localhost:9000/v1/session{endpoint}"
50 |
51 | def quiet(self):
52 | request_url = self._build_request_url(f"/{self._session_id}")
53 | self._delete(request_url)
54 |
55 | def _post(self, request_url: str, data: object):
56 | return requests.post(url = request_url, data = json.dumps(data))
57 |
58 | def _get(self, request_url: str):
59 | return requests.get(request_url)
60 |
61 | def _delete(self, request_url: str):
62 | return requests.delete(request_url)
63 |
64 | def launch_the_channel(self, channel_code):
65 | launch_response = self._send_launch_channel(channel_code)
66 | if launch_response.status_code != 200:
67 | raise Exception("Wrong launch response code")
68 |
69 | def verify_is_screen_loaded(self, data: object, invoke_error = True, retries = 10):
70 | while retries > 0:
71 | ui_layout_response = self._get_ui_element(data)
72 | if ui_layout_response.status_code != 200:
73 | retries -= 1
74 | sleep(1)
75 | else:
76 | return True
77 | if invoke_error == True:
78 | raise Exception("Can't find element")
79 | else:
80 | return False
81 |
82 | def press_btn(self, key_press: str):
83 | sleep(2)
84 | key_press_response = self._send_keypress(key_press)
85 | if key_press_response.status_code != 200:
86 | raise Exception("Wrong keypress response code")
87 |
88 | def send_word(self, word: str):
89 | sleep(2)
90 | for c in word:
91 | key_press_response = self._send_keypress(f"LIT_{c}")
92 | if key_press_response.status_code != 200:
93 | raise Exception("Wrong keypress response code")
94 |
95 | def send_button_sequence(self, sequence):
96 | key_press_response = self._send_sequence(sequence)
97 | if key_press_response.status_code != 200:
98 | raise Exception("Wrong keypress response code")
--------------------------------------------------------------------------------
/src/ecpClient/ecp_parser.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package ecpClient
17 |
18 | import (
19 | "net/http"
20 | "encoding/xml"
21 | "io/ioutil"
22 | "image/png"
23 | "image"
24 | )
25 |
26 | func (ec *EcpClient) parseApps(res *http.Response) (*[]App, error) {
27 | var apps AppsResponse
28 | result, err := ec.parseResponse(res, &apps)
29 | if err != nil {
30 | return nil, err
31 | }
32 | parsedRes := result.(*AppsResponse)
33 | return &parsedRes.Apps, err
34 | }
35 |
36 | func (ec *EcpClient) parsePlayer(res *http.Response) (*Player, error) {
37 | var player Player
38 | result, err := ec.parseResponse(res, &player)
39 | if err != nil {
40 | return nil, err
41 | }
42 | parsedRes := result.(*Player)
43 | return parsedRes, err
44 | }
45 |
46 | func (ec *EcpClient) parseActiveApp(res *http.Response) (*App, error) {
47 | var app ActiveAppResponse
48 | result, err := ec.parseResponse(res, &app)
49 | if err != nil {
50 | return nil, err
51 | }
52 | parsedRes := result.(*ActiveAppResponse)
53 | return &parsedRes.ActiveApp, err
54 | }
55 |
56 | func (ec *EcpClient) parseDeviceInfo(res *http.Response) (*DeviceInfo, error) {
57 | var responseStructure DeviceInfo
58 | result, err := ec.parseResponse(res, &responseStructure)
59 | if err != nil {
60 | return nil, err
61 | }
62 | parsedRes := result.(*DeviceInfo)
63 | return parsedRes, err
64 | }
65 |
66 | func (ec *EcpClient) parseAppUi(res *http.Response) (*Node, error) {
67 | var responseStructure Node
68 | result, err := ec.parseResponse(res, &responseStructure)
69 | if err != nil {
70 | return nil, err
71 | }
72 | parsedRes := result.(*Node)
73 | return parsedRes, err
74 | }
75 |
76 | func (ec *EcpClient) parseImage(res *http.Response) (image.Image, error) {
77 | result, err := png.Decode(res.Body)
78 | if err != nil {
79 | return nil, err
80 | }
81 | return result, err
82 | }
83 |
84 |
85 | func (ec *EcpClient) parseAppUiSource(res *http.Response) ([]byte, error) {
86 | data, err := ioutil.ReadAll(res.Body)
87 | if err != nil {
88 | return nil, err
89 | }
90 | return data, nil
91 | }
92 |
93 | func (ec *EcpClient) parseResponse(res *http.Response, v interface{}) (interface{}, error) {
94 | data, err := ioutil.ReadAll(res.Body)
95 | if err != nil {
96 | return nil, err
97 | }
98 | err = xml.Unmarshal(data, v)
99 | if err != nil {
100 | return nil, err
101 | }
102 | return v, err
103 | }
--------------------------------------------------------------------------------
/src/ecpClient/http_client.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package ecpClient
17 |
18 | import (
19 | "net/http"
20 | "time"
21 | )
22 |
23 | type Option func(*Client)
24 |
25 | func SetHTTPClient(httpClient *http.Client) Option {
26 | return func(cli *Client) {
27 | cli.HttpClient = httpClient
28 | }
29 | }
30 |
31 | func SetRequestTimeout(timeout time.Duration) Option {
32 | return func(cli *Client) {
33 | cli.HttpClient.Timeout = timeout
34 | }
35 | }
36 |
37 | type Client struct {
38 | HttpClient *http.Client
39 | }
40 |
41 | func NewClient(options ...Option) *Client {
42 | cli := Client{
43 | HttpClient: &http.Client{},
44 | }
45 |
46 | for i := range options {
47 | options[i](&cli)
48 | }
49 |
50 | return &cli
51 | }
52 |
--------------------------------------------------------------------------------
/src/ecpClient/http_client_mock.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package ecpClient
17 |
18 | import (
19 | "bytes"
20 | "io/ioutil"
21 | "net/http"
22 | "net/url"
23 | )
24 |
25 | var base, _ = url.Parse("some.api")
26 | // RoundTripFunc .
27 | type RoundTripFunc func(req *http.Request) (*http.Response, error)
28 |
29 | // RoundTrip .
30 | func (f RoundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
31 | return f(req)
32 | }
33 |
34 | //NewTestClient returns *http.Client with Transport replaced to avoid making real calls
35 | func NewTestClient(fn RoundTripFunc) *http.Client {
36 | return &http.Client{
37 | Transport: RoundTripFunc(fn),
38 | }
39 | }
40 |
41 | func GetMockedClient(resp *string) *EcpClient {
42 | httpClient := TestingHTTPClient(resp)
43 |
44 | cli := NewClient()
45 | cli.HttpClient = httpClient
46 |
47 | contentsClient := EcpClient{
48 | BaseClient: &BaseClient{
49 | BaseURL: base,
50 | HttpClient: cli,
51 | },
52 | }
53 |
54 | return &contentsClient
55 | }
56 |
57 |
58 | func TestingHTTPClient(resp *string) *http.Client {
59 | var function func(r *http.Request) (*http.Response, error)
60 | if resp != nil{
61 | function = func(req *http.Request) (*http.Response, error) {
62 | // Test request parameters
63 | return &http.Response{
64 | StatusCode: 200,
65 | // Send response to be tested
66 | Body: ioutil.NopCloser(bytes.NewBufferString(*resp)),
67 | // Must be set to non-nil value or it panics
68 | Header: make(http.Header),
69 | }, nil
70 | }
71 | } else {
72 | function = func(req *http.Request) (*http.Response, error) {
73 | return &http.Response{
74 | StatusCode: 408,
75 | // Send response to be tested
76 | Body: nil,
77 | // Must be set to non-nil value or it panics
78 | Header: make(http.Header),
79 | }, http.ErrHandlerTimeout
80 | }
81 | }
82 |
83 | cli := NewTestClient(function)
84 | return cli
85 | }
86 |
--------------------------------------------------------------------------------
/src/ecpClient/response_mocks.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package ecpClient
17 |
18 | var SuccessResponseMock = `{}`
19 |
20 | var AppResponseMock =`
21 |
22 | test
23 | `
24 |
25 | var AppsResponseMock = `
26 |
27 | test
28 | test2
29 | `
30 |
31 | var deviceInfoResponse =`
32 |
33 | test
34 | test
35 | test
36 | test
37 | test
38 | test
39 | test
40 | test
41 | test
42 | test
43 | test
44 | test
45 | test
46 | test
47 | test
48 | test
49 | test
50 | test
51 | test
52 | test
53 | test
54 | test
55 | test
56 | test
57 | test
58 | test
59 | test
60 | test
61 | test
62 | test
63 | test
64 | test
65 | test
66 | test
67 | test
68 | test
69 | test
70 | test
71 | test
72 | test
73 | test
74 | test
75 | test
76 | test
77 | test
78 | test
79 | test
80 | test
81 | test
82 | test
83 | test
84 | test
85 | test
86 | test
87 | test
88 | test
89 | test
90 | test
91 | test
92 | test
93 | `
94 |
95 | var UiResponseMock = `
96 |
97 |
98 |
99 | `
--------------------------------------------------------------------------------
/src/ecpClient/response_structure.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package ecpClient
17 |
18 | import (
19 | "encoding/xml"
20 | )
21 | type AppsResponse struct {
22 | Apps []App `xml:"app"`
23 | }
24 |
25 | type App struct {
26 | Title string `xml:",chardata"`
27 | ID string `xml:"id,attr"`
28 | Type string `xml:"type,attr"`
29 | Version string `xml:"version,attr"`
30 | Subtype string `xml:"subtype,attr"`
31 | }
32 |
33 | type Player struct {
34 | Error string `xml:"error,attr"`
35 | State string `xml:"state,attr"`
36 | Format struct {
37 | Audio string `xml:"audio,attr"`
38 | Captions string `xml:"captions,attr"`
39 | Container string `xml:"container,attr"`
40 | Drm string `xml:"drm,attr"`
41 | Video string `xml:"video,attr"`
42 | VideoRes string `xml:"video_res,attr"`
43 | } `xml:"format"`
44 | Buffering struct {
45 | Current string `xml:"current,attr"`
46 | Max string `xml:"max,attr"`
47 | Target string `xml:"target,attr"`
48 | } `xml:"buffering"`
49 | NewStream struct {
50 | Speed string `xml:"speed,attr"`
51 | } `xml:"new_stream"`
52 | Position string `xml:"position"`
53 | Duration string `xml:"duration"`
54 | IsLive string `xml:"is_live"`
55 | Runtime string `xml:"runtime"`
56 | StreamSegment struct {
57 | Bitrate string `xml:"bitrate,attr"`
58 | MediaSequence string `xml:"media_sequence,attr"`
59 | SegmentType string `xml:"segment_type,attr"`
60 | Time string `xml:"time,attr"`
61 | } `xml:"stream_segment"`
62 | }
63 |
64 | type ActiveAppResponse struct {
65 | ActiveApp App `xml:"app"`
66 | }
67 |
68 | type Node struct {
69 | XMLName xml.Name
70 | Attrs []xml.Attr `xml:",any,attr"`
71 | Nodes []Node `xml:",any"`
72 | }
73 |
74 | type DeviceInfo struct {
75 | Udn string `xml:"udn"`
76 | SerialNumber string `xml:"serial-number"`
77 | DeviceID string `xml:"device-id"`
78 | AdvertisingID string `xml:"advertising-id"`
79 | VendorName string `xml:"vendor-name"`
80 | ModelName string `xml:"model-name"`
81 | ModelNumber string `xml:"model-number"`
82 | ModelRegion string `xml:"model-region"`
83 | IsTv string `xml:"is-tv"`
84 | IsStick string `xml:"is-stick"`
85 | SupportsEthernet string `xml:"supports-ethernet"`
86 | WifiMac string `xml:"wifi-mac"`
87 | WifiDriver string `xml:"wifi-driver"`
88 | EthernetMac string `xml:"ethernet-mac"`
89 | NetworkType string `xml:"network-type"`
90 | NetworkName string `xml:"network-name"`
91 | FriendlyDeviceName string `xml:"friendly-device-name"`
92 | FriendlyModelName string `xml:"friendly-model-name"`
93 | DefaultDeviceName string `xml:"default-device-name"`
94 | UserDeviceName string `xml:"user-device-name"`
95 | UserDeviceLocation string `xml:"user-device-location"`
96 | BuildNumber string `xml:"build-number"`
97 | SoftwareVersion string `xml:"software-version"`
98 | SoftwareBuild string `xml:"software-build"`
99 | SecureDevice string `xml:"secure-device"`
100 | Language string `xml:"language"`
101 | Country string `xml:"country"`
102 | Locale string `xml:"locale"`
103 | TimeZoneAuto string `xml:"time-zone-auto"`
104 | TimeZone string `xml:"time-zone"`
105 | TimeZoneName string `xml:"time-zone-name"`
106 | TimeZoneTz string `xml:"time-zone-tz"`
107 | TimeZoneOffset string `xml:"time-zone-offset"`
108 | ClockFormat string `xml:"clock-format"`
109 | Uptime string `xml:"uptime"`
110 | PowerMode string `xml:"power-mode"`
111 | SupportsSuspend string `xml:"supports-suspend"`
112 | SupportsFindRemote string `xml:"supports-find-remote"`
113 | FindRemoteIsPossible string `xml:"find-remote-is-possible"`
114 | SupportsAudioGuide string `xml:"supports-audio-guide"`
115 | SupportsRva string `xml:"supports-rva"`
116 | DeveloperEnabled string `xml:"developer-enabled"`
117 | KeyedDeveloperID string `xml:"keyed-developer-id"`
118 | SearchEnabled string `xml:"search-enabled"`
119 | SearchChannelsEnabled string `xml:"search-channels-enabled"`
120 | NotificationsEnabled string `xml:"notifications-enabled"`
121 | NotificationsFirstUse string `xml:"notifications-first-use"`
122 | SupportsPrivateListening string `xml:"supports-private-listening"`
123 | HeadphonesConnected string `xml:"headphones-connected"`
124 | SupportsEcsTextedit string `xml:"supports-ecs-textedit"`
125 | SupportsEcsMicrophone string `xml:"supports-ecs-microphone"`
126 | SupportsWakeOnWlan string `xml:"supports-wake-on-wlan"`
127 | HasPlayOnRoku string `xml:"has-play-on-roku"`
128 | HasMobileScreensaver string `xml:"has-mobile-screensaver"`
129 | SupportURL string `xml:"support-url"`
130 | GrandcentralVersion string `xml:"grandcentral-version"`
131 | TrcVersion string `xml:"trc-version"`
132 | TrcChannelVersion string `xml:"trc-channel-version"`
133 | DavinciVersion string `xml:"davinci-version"`
134 | }
135 |
--------------------------------------------------------------------------------
/src/httpServer/middleware.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package httpServer
17 |
18 | import(
19 | "net/http"
20 | "encoding/json"
21 | )
22 |
23 | type errorResponse struct {
24 | Message string `json:"message"`
25 | }
26 |
27 | func Middleware(h appHandler) http.Handler {
28 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
29 | if e := h(w, r); e != nil {
30 | if e.InternalCode != nil {
31 | w.WriteHeader(e.Code)
32 | errorResponse := &errorResponse{
33 | Message: e.Message,
34 | }
35 | response := &SessionResponse{
36 | Status: *e.InternalCode,
37 | Value: errorResponse,
38 | }
39 | js, _ := json.Marshal(response)
40 | w.Header().Set("Content-Type", "application/json")
41 | w.Write(js)
42 | } else {
43 | http.Error(w, e.Message, e.Code)
44 | }
45 |
46 | }
47 | })
48 | }
--------------------------------------------------------------------------------
/src/httpServer/response_mock.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package httpServer
17 |
18 | var validAppsResponse = `
19 | {
20 | "sessionId": "test",
21 | "status": 0,
22 | "value": [
23 | {
24 | "Title": "test",
25 | "ID": "test",
26 | "Type": "test",
27 | "Version": "test",
28 | "Subtype": "test"
29 | },
30 | {
31 | "Title": "test2",
32 | "ID": "test2",
33 | "Type": "test2",
34 | "Version": "test2",
35 | "Subtype": "test2"
36 | }
37 | ]
38 | }`
39 |
40 | var validAppResponse = `
41 | {
42 | "sessionId": "test",
43 | "status": 0,
44 | "value": {
45 | "Title": "test",
46 | "ID": "test",
47 | "Type": "test",
48 | "Version": "test",
49 | "Subtype": "test"
50 | }
51 | }`
52 |
53 | var validResponseWithNullValue = `
54 | {
55 | "sessionId": "test",
56 | "status": 0,
57 | "value": null
58 | }`
59 |
60 | var validSessionResponse = `
61 | {
62 | "sessionId":"test",
63 | "status":0,
64 | "value": {
65 | "country":"",
66 | "ip":"",
67 | "language":"",
68 | "modelName":"",
69 | "vendorName":"",
70 | "pressDelay": 0,
71 | "timeout": 0
72 | }
73 | }`
74 |
75 | var validSessionsResponse = `[
76 | {
77 | "sessionId":"test",
78 | "status":0,
79 | "value": {
80 | "country":"",
81 | "ip":"",
82 | "language":"",
83 | "modelName":"",
84 | "vendorName":"",
85 | "pressDelay": 0,
86 | "timeout": 0
87 | }
88 | }]`
89 |
90 | var validElementResponse = `
91 | {
92 | "sessionId":"test",
93 | "status":0,
94 | "value": {
95 | "XMLName": {
96 | "Local": "Poster",
97 | "Space": ""
98 | },
99 | "Attrs": [
100 | {
101 | "Name": {
102 | "Local": "bounds",
103 | "Space": ""
104 | },
105 | "Value": "{0, 0, 1920, 1080}"
106 | },
107 | {
108 | "Name": {
109 | "Local": "index",
110 | "Space": ""
111 | },
112 | "Value": "0"
113 | },
114 | {
115 | "Name": {
116 | "Local": "loadStatus",
117 | "Space": ""
118 | },
119 | "Value": "3"
120 | }
121 | ],
122 | "Nodes": null
123 | }
124 | }`
125 |
126 | var validElementsResponse = `
127 | {
128 | "sessionId":"test",
129 | "status":0,
130 | "value": [{
131 | "XMLName": {
132 | "Local": "Poster",
133 | "Space": ""
134 | },
135 | "Attrs": [
136 | {
137 | "Name": {
138 | "Local": "bounds",
139 | "Space": ""
140 | },
141 | "Value": "{0, 0, 1920, 1080}"
142 | },
143 | {
144 | "Name": {
145 | "Local": "index",
146 | "Space": ""
147 | },
148 | "Value": "0"
149 | },
150 | {
151 | "Name": {
152 | "Local": "loadStatus",
153 | "Space": ""
154 | },
155 | "Value": "3"
156 | }
157 | ],
158 | "Nodes": null
159 | }]
160 | }`
--------------------------------------------------------------------------------
/src/httpServer/response_structure.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package httpServer
17 |
18 | type BuildInfo struct {
19 | Version string `json:"version"`
20 | Time string `json:"time"`
21 | }
22 |
23 | type OsInfo struct {
24 | Arch string `json:"arch"`
25 | Name string `json:"name"`
26 | }
27 |
28 | type Status struct {
29 | Build BuildInfo `json:"build"`
30 | Os OsInfo `json:"os"`
31 | }
32 |
33 | type Capability struct {
34 | Ip string `json:"ip"`
35 | Timeout int `json:"timeout"`
36 | PressDelay int `json:"pressDelay"`
37 | VendorName string `json:"vendorName"`
38 | ModelName string `json:"modelName"`
39 | Language string `json:"language"`
40 | Country string `json:"country"`
41 | }
42 |
43 | type SessionResponse struct {
44 | Id string `json:"sessionId"`
45 | Status int `json:"status"`
46 | Value interface{} `json:"value"`
47 | }
48 |
49 | var responseStatuses = map[string]int {
50 | "Success": 0,
51 | "NoSuchDriver": 6,
52 | "NoSuchElement": 7,
53 | "UnknownCommand": 9,
54 | "UnknownError": 13,
55 | "SessionNotCreatedException": 33,
56 | }
57 |
58 | type ButtonRequest struct {
59 | Button string `json:"button"`
60 | Button_sequence []string `json:"button_sequence"`
61 | Button_delays []string `json:"button_delays"`
62 | }
63 |
64 | type Element struct {
65 | Using string `json:"using"`
66 | Value string `json:"value"`
67 | Attribute string `json:"attribute"`
68 | }
69 |
70 | type ElementRequest struct {
71 | ParentData []Element `json:"parentData"`
72 | ElementData []Element `json:"elementData"`
73 | }
74 |
75 | type ChannelRequest struct {
76 | ChannelId string `json:"channelId"`
77 | ContentType string `json:"contentType"`
78 | ContentId string `json:"contentId"`
79 | }
80 |
81 | type TimeoutRequest struct {
82 | Type string `json:"type"`
83 | Ms int `json:"ms"`
84 | }
85 |
86 | type IntentRequest struct {
87 | Intent string `json:"intent"`
88 | }
--------------------------------------------------------------------------------
/src/httpServer/routing.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package httpServer
17 |
18 | import(
19 | "net/http"
20 | )
21 |
22 | type Route struct {
23 | Method string
24 | Pattern string
25 | HandlerFunc appHandler
26 | }
27 |
28 | type Routes []Route
29 |
30 | func (s *Server) SetUpRoutes() {
31 | routes := Routes{
32 | Route{
33 | "GET",
34 | "/v1/status",
35 | s.GetStatusHandler(),
36 | },
37 | Route{
38 | "POST",
39 | "/v1/session/{sessionId}/load",
40 | s.GetLoadHandler(),
41 | },
42 | Route{
43 | "POST",
44 | "/v1/session",
45 | s.GetStartSessionHandler(),
46 | },
47 | Route{
48 | "GET",
49 | "/v1/sessions",
50 | s.GetSessionsInfoHandler(),
51 | },
52 | Route{
53 | "GET",
54 | "/v1/session/{sessionId}",
55 | s.GetSessionHandler(),
56 | },
57 | Route{
58 | "DELETE",
59 | "/v1/session/{sessionId}",
60 | s.GetSessionDeleteHandler(),
61 | },
62 | Route{
63 | "POST",
64 | "/v1/session/{sessionId}/timeouts",
65 | s.GetTimeoutsHandler(),
66 | },
67 | Route{
68 | "POST",
69 | "/v1/session/{sessionId}/element",
70 | s.GetElementHandler(),
71 | },
72 | Route{
73 | "GET",
74 | "/v1/session/{sessionId}/player",
75 | s.GetPlayerHandler(),
76 | },
77 | Route{
78 | "POST",
79 | "/v1/session/{sessionId}/elements",
80 | s.GetElementsHandler(),
81 | },
82 | Route{
83 | "POST",
84 | "/v1/session/{sessionId}/element/active",
85 | s.GetActiveElementHandler(),
86 | },
87 | Route{
88 | "GET",
89 | "/v1/session/{sessionId}/apps",
90 | s.GetAppsHandler(),
91 | },
92 | Route{
93 | "GET",
94 | "/v1/session/{sessionId}/current_app",
95 | s.GetCurrentAppHandler(),
96 | },
97 | Route{
98 | "GET",
99 | "/v1/session/{sessionId}/source",
100 | s.GetSourceHandler(),
101 | },
102 | Route{
103 | "POST",
104 | "/v1/session/{sessionId}/press",
105 | s.GetPressButtonHandler(),
106 | },
107 | Route{
108 | "POST",
109 | "/v1/session/{sessionId}/launch",
110 | s.GetLaunchHandler(),
111 | },
112 | Route{
113 | "POST",
114 | "/v1/session/{sessionId}/input",
115 | s.GetInputHandler(),
116 | },
117 | Route{
118 | "POST",
119 | "/v1/session/{sessionId}/timeouts/implicit_wait",
120 | s.GetImplicitTimeoutHandler(),
121 | },
122 | Route{
123 | "POST",
124 | "/v1/session/{sessionId}/timeouts/press_wait",
125 | s.GetImplicitTimeoutHandler(),
126 | },
127 | Route{
128 | "POST",
129 | "/v1/session/{sessionId}/install",
130 | s.GetInstallHandler(),
131 | },
132 | }
133 |
134 |
135 | for _, route := range routes {
136 | s.router.
137 | Methods(route.Method).
138 | Path(route.Pattern).
139 | Handler(Middleware(route.HandlerFunc)).GetError()
140 | }
141 | s.router.NotFoundHandler = http.Handler(Middleware(s.notFound()))
142 | http.Handle("/", s.router)
143 | }
--------------------------------------------------------------------------------
/src/httpServer/server.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package httpServer
17 |
18 | import (
19 | "github.com/gorilla/mux"
20 | ecp "ecpClient"
21 | "net/http"
22 | "time"
23 | "github.com/sirupsen/logrus"
24 | )
25 |
26 |
27 |
28 | type Server struct {
29 | router *mux.Router
30 | sessions map[string]*SessionInfo
31 | }
32 |
33 | type SessionInfo struct {
34 | client *ecp.EcpClient
35 | plugin *ecp.PluginClient
36 | capability *Capability
37 | pressDelay time.Duration
38 | }
39 |
40 | func GetServerInstance() *Server {
41 | server := &Server{
42 | router: mux.NewRouter(),
43 | sessions: make(map[string]*SessionInfo),
44 | }
45 |
46 | return server
47 | }
48 |
49 | func (s *Server) Start(port string) {
50 | s.SetUpRoutes()
51 | err := http.ListenAndServe(":" + port, nil)
52 | if err != http.ErrServerClosed {
53 | logrus.WithError(err).Error("Http Server stopped unexpected")
54 | } else {
55 | logrus.WithError(err).Info("Http Server stopped")
56 | }
57 | }
--------------------------------------------------------------------------------
/src/httpServer/utils.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package httpServer
17 |
18 | import (
19 | "regexp"
20 | "strings"
21 | )
22 |
23 | func validIP4(ipAddress string) bool {
24 | ipAddress = strings.Trim(ipAddress, " ")
25 |
26 | re, _ := regexp.Compile(`^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$`)
27 | if re.MatchString(ipAddress) {
28 | return true
29 | }
30 | return false
31 | }
--------------------------------------------------------------------------------
/src/main.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package main
17 |
18 | import (
19 | "fmt"
20 | httpServer "httpServer"
21 | "os"
22 | "regexp"
23 | )
24 |
25 | func main() {
26 | defaultPort := "9000"
27 | validPort := regexp.MustCompile(`^[0-9]+$`)
28 | server := httpServer.GetServerInstance()
29 | if len(os.Args) > 1 && validPort.MatchString(os.Args[1]) {
30 | fmt.Println("Starting driver on port: " + os.Args[1])
31 | server.Start(os.Args[1])
32 | } else {
33 | fmt.Println("Starting driver on port: " + defaultPort)
34 | server.Start(defaultPort)
35 | }
36 | }
--------------------------------------------------------------------------------
/src/version/version.go:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////
2 | // Copyright 2019 Roku, Inc.
3 | //
4 | //Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | //You may obtain a copy of the License at
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | //Unless required by applicable law or agreed to in writing, software
10 | //distributed under the License is distributed on an "AS IS" BASIS,
11 | //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | //See the License for the specific language governing permissions and
13 | //limitations under the License.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | package version
17 |
18 | var (
19 | BuildVersion string = ""
20 | BuildTime string = ""
21 | )
--------------------------------------------------------------------------------