| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 /** @fileoverview Suite of tests for media-router-container. */ |
| 6 cr.define('media_router_container_route', function() { |
| 7 function registerTests() { |
| 8 suite('MediaRouterContainerRoute', function() { |
| 9 /** |
| 10 * Media Router Container created before each test. |
| 11 * @type {MediaRouterContainer} |
| 12 */ |
| 13 var container; |
| 14 |
| 15 /** |
| 16 * The blocking issue to show. |
| 17 * @type {?media_router.Issue} |
| 18 */ |
| 19 var fakeBlockingIssue; |
| 20 |
| 21 /** |
| 22 * The list of CastModes to show. |
| 23 * @type {!Array<!media_router.CastMode>} |
| 24 */ |
| 25 var fakeCastModeList = []; |
| 26 |
| 27 /** |
| 28 * The list of CastModes to show with non-default modes only. |
| 29 * @type {!Array<!media_router.CastMode>} |
| 30 */ |
| 31 var fakeCastModeListWithNonDefaultModesOnly = []; |
| 32 |
| 33 /** |
| 34 * The blocking issue to show. |
| 35 * @type {?media_router.Issue} |
| 36 */ |
| 37 var fakeNonBlockingIssue; |
| 38 |
| 39 /** |
| 40 * The list of current routes. |
| 41 * @type {!Array<!media_router.Route>} |
| 42 */ |
| 43 var fakeRouteList = []; |
| 44 |
| 45 /** |
| 46 * The list of available sinks. |
| 47 * @type {!Array<!media_router.Sink>} |
| 48 */ |
| 49 var fakeSinkList = []; |
| 50 |
| 51 /** |
| 52 * The list of elements to check for visibility. |
| 53 * @const {!Array<string>} |
| 54 */ |
| 55 var hiddenCheckElementIdList = [ |
| 56 'cast-mode-list', |
| 57 'container-header', |
| 58 'device-missing', |
| 59 'first-run-flow', |
| 60 'first-run-flow-cloud-pref', |
| 61 'issue-banner', |
| 62 'no-search-matches', |
| 63 'route-details', |
| 64 'search-results', |
| 65 'sink-list', |
| 66 'sink-list-view', |
| 67 ]; |
| 68 |
| 69 // Checks whether |view| matches the current view of |container|. |
| 70 var checkCurrentView = function(view) { |
| 71 assertEquals(view, container.currentView_); |
| 72 }; |
| 73 |
| 74 // Checks whether the elements specified in |elementIdList| are visible. |
| 75 // Checks whether all other elements are not visible. |
| 76 var checkElementsVisibleWithId = function(elementIdList) { |
| 77 for (var i = 0; i < elementIdList.length; i++) |
| 78 checkElementVisibleWithId(true, elementIdList[i]); |
| 79 |
| 80 for (var j = 0; j < hiddenCheckElementIdList.length; j++) { |
| 81 if (elementIdList.indexOf(hiddenCheckElementIdList[j]) == -1) |
| 82 checkElementVisibleWithId(false, hiddenCheckElementIdList[j]); |
| 83 } |
| 84 }; |
| 85 |
| 86 // Checks the visibility of an element with |elementId| in |container|. |
| 87 // An element is considered visible if it exists and its |hidden| property |
| 88 // is |false|. |
| 89 var checkElementVisibleWithId = function(visible, elementId) { |
| 90 var element = container.$$('#' + elementId); |
| 91 var elementVisible = !!element && !element.hidden && |
| 92 element.style.display != 'none'; |
| 93 assertEquals(visible, elementVisible, elementId); |
| 94 }; |
| 95 |
| 96 // Checks whether |expected| and the text in the |element| are equal. |
| 97 var checkElementText = function(expected, element) { |
| 98 assertEquals(expected.trim(), element.textContent.trim()); |
| 99 }; |
| 100 |
| 101 // Import media_router_container.html before running suite. |
| 102 suiteSetup(function() { |
| 103 return PolymerTest.importHtml( |
| 104 'chrome://media-router/elements/media_router_container/' + |
| 105 'media_router_container.html'); |
| 106 }); |
| 107 |
| 108 // Initialize a media-router-container before each test. |
| 109 setup(function(done) { |
| 110 PolymerTest.clearBody(); |
| 111 container = document.createElement('media-router-container'); |
| 112 document.body.appendChild(container); |
| 113 |
| 114 // Initialize local variables. |
| 115 fakeCastModeList = [ |
| 116 new media_router.CastMode(0x1, 'Description 0', 'google.com'), |
| 117 new media_router.CastMode(0x2, 'Description 1', null), |
| 118 new media_router.CastMode(0x4, 'Description 2', null), |
| 119 ]; |
| 120 |
| 121 fakeCastModeListWithNonDefaultModesOnly = [ |
| 122 new media_router.CastMode(0x2, 'Description 1', null), |
| 123 new media_router.CastMode(0x4, 'Description 2', null), |
| 124 new media_router.CastMode(0x8, 'Description 3', null), |
| 125 ]; |
| 126 |
| 127 fakeRouteList = [ |
| 128 new media_router.Route('id 1', 'sink id 1', |
| 129 'Title 1', 0, true, false), |
| 130 new media_router.Route('id 2', 'sink id 2', |
| 131 'Title 2', 1, false, true), |
| 132 ]; |
| 133 |
| 134 fakeRouteListWithLocalRoutesOnly = [ |
| 135 new media_router.Route('id 1', 'sink id 1', |
| 136 'Title 1', 0, true, false), |
| 137 new media_router.Route('id 2', 'sink id 2', |
| 138 'Title 2', 1, true, false), |
| 139 ]; |
| 140 |
| 141 var castModeBitset = 0x2 | 0x4 | 0x8; |
| 142 fakeSinkList = [ |
| 143 new media_router.Sink('sink id 1', 'Sink 1', null, null, |
| 144 media_router.SinkIconType.CAST, |
| 145 media_router.SinkStatus.ACTIVE, castModeBitset), |
| 146 new media_router.Sink('sink id 2', 'Sink 2', null, null, |
| 147 media_router.SinkIconType.CAST, |
| 148 media_router.SinkStatus.ACTIVE, castModeBitset), |
| 149 new media_router.Sink('sink id 3', 'Sink 3', null, null, |
| 150 media_router.SinkIconType.CAST, |
| 151 media_router.SinkStatus.PENDING, castModeBitset), |
| 152 ]; |
| 153 |
| 154 fakeBlockingIssue = new media_router.Issue( |
| 155 'issue id 1', 'Issue Title 1', 'Issue Message 1', 0, 1, |
| 156 'route id 1', true, 1234); |
| 157 |
| 158 fakeNonBlockingIssue = new media_router.Issue( |
| 159 'issue id 2', 'Issue Title 2', 'Issue Message 2', 0, 1, |
| 160 'route id 2', false, 1234); |
| 161 |
| 162 container.castModeList = fakeCastModeList; |
| 163 |
| 164 // Allow for the media router container to be created and attached. |
| 165 setTimeout(done); |
| 166 }); |
| 167 |
| 168 // Tests for 'create-route' event firing when a sink with no associated |
| 169 // route is clicked. |
| 170 test('select sink without a route', function(done) { |
| 171 container.allSinks = fakeSinkList; |
| 172 |
| 173 setTimeout(function() { |
| 174 var sinkList = |
| 175 container.$['sink-list'].querySelectorAll('paper-item'); |
| 176 container.addEventListener('create-route', function(data) { |
| 177 // Container is initially in auto mode since a cast mode has not |
| 178 // been selected. |
| 179 assertEquals(media_router.CastModeType.AUTO, |
| 180 container.shownCastModeValue_); |
| 181 assertEquals(fakeSinkList[2].id, data.detail.sinkId); |
| 182 |
| 183 // The preferred compatible cast mode on the sink is used, since |
| 184 // the we did not choose a cast mode on the container. |
| 185 assertEquals(0x2, data.detail.selectedCastModeValue); |
| 186 done(); |
| 187 }); |
| 188 // Tap on a sink without a route, which should fire a 'create-route' |
| 189 // event. |
| 190 assertEquals(fakeSinkList.length, sinkList.length); |
| 191 MockInteractions.tap(sinkList[2]); |
| 192 }); |
| 193 }); |
| 194 |
| 195 // Tests that selecting a sink with an associated route will make the |
| 196 // |container| switch to ROUTE_DETAILS view. |
| 197 test('select sink with a route', function(done) { |
| 198 container.allSinks = fakeSinkList; |
| 199 container.routeList = fakeRouteList; |
| 200 |
| 201 setTimeout(function() { |
| 202 var sinkList = |
| 203 container.$['sink-list'].querySelectorAll('paper-item'); |
| 204 |
| 205 // Start from the SINK_LIST view. |
| 206 container.showSinkList_(); |
| 207 checkCurrentView(media_router.MediaRouterView.SINK_LIST); |
| 208 MockInteractions.tap(sinkList[0]); |
| 209 checkCurrentView(media_router.MediaRouterView.ROUTE_DETAILS); |
| 210 done(); |
| 211 }); |
| 212 }); |
| 213 |
| 214 // Tests the text shown for the sink list. |
| 215 test('initial sink list route text', function(done) { |
| 216 // Sink 1 - no sink description, no route -> no subtext |
| 217 // Sink 2 - sink description, no route -> subtext = sink description |
| 218 // Sink 3 - no sink description, route -> subtext = route description |
| 219 // Sink 4 - sink description, route -> subtext = route description |
| 220 container.allSinks = [ |
| 221 new media_router.Sink('sink id 1', 'Sink 1', null, null, |
| 222 media_router.SinkIconType.CAST, |
| 223 media_router.SinkStatus.ACTIVE, [1, 2, 3]), |
| 224 new media_router.Sink('sink id 2', 'Sink 2', |
| 225 'Sink 2 description', null, |
| 226 media_router.SinkIconType.CAST, |
| 227 media_router.SinkStatus.ACTIVE, [1, 2, 3]), |
| 228 new media_router.Sink('sink id 3', 'Sink 3', null, null, |
| 229 media_router.SinkIconType.CAST, |
| 230 media_router.SinkStatus.PENDING, [1, 2, 3]), |
| 231 new media_router.Sink('sink id 4', 'Sink 4', |
| 232 'Sink 4 description', null, |
| 233 media_router.SinkIconType.CAST, |
| 234 media_router.SinkStatus.PENDING, [1, 2, 3]) |
| 235 ]; |
| 236 |
| 237 container.routeList = [ |
| 238 new media_router.Route('id 3', 'sink id 3', 'Title 3', 0, true), |
| 239 new media_router.Route('id 4', 'sink id 4', 'Title 4', 1, false), |
| 240 ]; |
| 241 |
| 242 setTimeout(function() { |
| 243 var sinkSubtextList = |
| 244 container.$['sink-list'].querySelectorAll('.sink-subtext'); |
| 245 |
| 246 // There will only be 3 sink subtext entries, because Sink 1 does not |
| 247 // have any subtext. |
| 248 assertEquals(3, sinkSubtextList.length); |
| 249 |
| 250 checkElementText(container.allSinks[1].description, |
| 251 sinkSubtextList[0]); |
| 252 |
| 253 // Route description overrides sink description for subtext. |
| 254 checkElementText(container.routeList[0].description, |
| 255 sinkSubtextList[1]); |
| 256 |
| 257 checkElementText(container.routeList[1].description, |
| 258 sinkSubtextList[2]); |
| 259 done(); |
| 260 }); |
| 261 }); |
| 262 |
| 263 // Tests the expected view when there is only one local active route and |
| 264 // media_router_container is created for the first time. |
| 265 test('initial view with one local route', function() { |
| 266 container.allSinks = fakeSinkList; |
| 267 container.routeList = fakeRouteList; |
| 268 container.maybeShowRouteDetailsOnOpen(); |
| 269 |
| 270 checkCurrentView(media_router.MediaRouterView.ROUTE_DETAILS); |
| 271 }); |
| 272 |
| 273 // Tests the expected view when there are multiple local active routes |
| 274 // and media_router_container is created for the first time. |
| 275 test('initial view with multiple local routes', function() { |
| 276 container.allSinks = fakeSinkList; |
| 277 container.routeList = fakeRouteListWithLocalRoutesOnly; |
| 278 |
| 279 checkCurrentView(media_router.MediaRouterView.SINK_LIST); |
| 280 }); |
| 281 |
| 282 // Tests the expected view when there are no local active routes and |
| 283 // media_router_container is created for the first time. |
| 284 test('initial view with no local route', function() { |
| 285 container.allSinks = fakeSinkList; |
| 286 container.routeList = []; |
| 287 |
| 288 checkCurrentView(media_router.MediaRouterView.SINK_LIST); |
| 289 }); |
| 290 |
| 291 // Tests the expected view when there are no local active routes and |
| 292 // media_router_container is created for the first time. |
| 293 test('view after route is closed remotely', function() { |
| 294 container.allSinks = fakeSinkList; |
| 295 container.routeList = fakeRouteList; |
| 296 container.maybeShowRouteDetailsOnOpen(); |
| 297 checkCurrentView(media_router.MediaRouterView.ROUTE_DETAILS); |
| 298 |
| 299 container.routeList = []; |
| 300 checkCurrentView(media_router.MediaRouterView.SINK_LIST); |
| 301 }); |
| 302 |
| 303 // Tests for expected visible UI when the view is ROUTE_DETAILS. |
| 304 test('route details visibility', function(done) { |
| 305 container.showRouteDetails_(); |
| 306 setTimeout(function() { |
| 307 checkElementsVisibleWithId(['container-header', |
| 308 'device-missing', |
| 309 'route-details']); |
| 310 done(); |
| 311 }); |
| 312 }); |
| 313 |
| 314 test('updated route in route details', function(done) { |
| 315 container.allSinks = fakeSinkList; |
| 316 var description = 'Title'; |
| 317 var route = new media_router.Route( |
| 318 'id 1', 'sink id 1', description, 0, true, false); |
| 319 container.routeList = [route]; |
| 320 container.showRouteDetails_(route); |
| 321 setTimeout(function() { |
| 322 // Note that sink-list-view is hidden. |
| 323 checkElementsVisibleWithId( |
| 324 ['container-header', 'route-details', 'sink-list']); |
| 325 assertTrue(!!container.currentRoute_); |
| 326 assertEquals(description, container.currentRoute_.description); |
| 327 |
| 328 var newDescription = 'Foo'; |
| 329 route.description = newDescription; |
| 330 container.routeList = [route]; |
| 331 setTimeout(function() { |
| 332 // Note that sink-list-view is hidden. |
| 333 checkElementsVisibleWithId( |
| 334 ['container-header', 'route-details', 'sink-list']); |
| 335 assertTrue(!!container.currentRoute_); |
| 336 assertEquals(newDescription, container.currentRoute_.description); |
| 337 done(); |
| 338 }); |
| 339 }); |
| 340 }); |
| 341 |
| 342 // Tests for expected visible UI when the view is ROUTE_DETAILS, and there |
| 343 // is a non-blocking issue. |
| 344 test('route details visibility non blocking issue', function(done) { |
| 345 container.showRouteDetails_(); |
| 346 |
| 347 // Set a non-blocking issue. The issue should be shown. |
| 348 container.issue = fakeNonBlockingIssue; |
| 349 setTimeout(function() { |
| 350 checkElementsVisibleWithId(['container-header', |
| 351 'device-missing', |
| 352 'route-details']); |
| 353 done(); |
| 354 }); |
| 355 }); |
| 356 |
| 357 // Tests for expected visible UI when the view is ROUTE_DETAILS, and there |
| 358 // is a blocking issue. |
| 359 test('route details visibility with blocking issue', function(done) { |
| 360 container.showRouteDetails_(); |
| 361 |
| 362 // Set a blocking issue. The issue should be shown, and everything |
| 363 // else, hidden. |
| 364 container.issue = fakeBlockingIssue; |
| 365 setTimeout(function() { |
| 366 checkElementsVisibleWithId(['container-header', |
| 367 'device-missing', |
| 368 'issue-banner']); |
| 369 done(); |
| 370 }); |
| 371 }); |
| 372 |
| 373 test('creating route with selected cast mode', function(done) { |
| 374 container.allSinks = fakeSinkList; |
| 375 MockInteractions.tap(container.$['container-header']. |
| 376 $['arrow-drop-icon']); |
| 377 setTimeout(function() { |
| 378 // Select cast mode 2. |
| 379 var castModeList = |
| 380 container.$$('#cast-mode-list').querySelectorAll('paper-item'); |
| 381 MockInteractions.tap(castModeList[1]); |
| 382 assertEquals(fakeCastModeList[1].description, container.headerText); |
| 383 setTimeout(function() { |
| 384 var sinkList = |
| 385 container.$['sink-list'].querySelectorAll('paper-item'); |
| 386 container.addEventListener('create-route', function(data) { |
| 387 assertEquals(fakeSinkList[2].id, data.detail.sinkId); |
| 388 // Cast mode 2 is used, since we selected it explicitly. |
| 389 assertEquals(fakeCastModeList[1].type, |
| 390 data.detail.selectedCastModeValue); |
| 391 done(); |
| 392 }); |
| 393 // All sinks are compatible with cast mode 2. |
| 394 assertEquals(fakeSinkList.length, sinkList.length); |
| 395 // Tap on a sink without a route, which should fire a 'create-route' |
| 396 // event. |
| 397 MockInteractions.tap(sinkList[2]); |
| 398 }); |
| 399 }); |
| 400 }); |
| 401 }); |
| 402 } |
| 403 |
| 404 return { |
| 405 registerTests: registerTests, |
| 406 }; |
| 407 }); |
| OLD | NEW |