1 // Copyright 2015 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.
5 /** @fileoverview Suite of tests for media-router-container. */
6 cr.define('media_router_container', function() {
7 function registerTests() {
8 suite('MediaRouterContainer', function() {
10 * Media Router Container created before each test.
11 * @type {MediaRouterContainer}
16 * The blocking issue to show.
17 * @type {?media_router.Issue}
19 var fakeBlockingIssue;
22 * The list of CastModes to show.
23 * @type {!Array<!media_router.CastMode>}
25 var fakeCastModeList = [];
28 * The list of CastModes to show with non-default modes only.
29 * @type {!Array<!media_router.CastMode>}
31 var fakeCastModeListWithNonDefaultModesOnly = [];
34 * The blocking issue to show.
35 * @type {?media_router.Issue}
37 var fakeNonBlockingIssue;
40 * The list of current routes.
41 * @type {!Array<!media_router.Route>}
43 var fakeRouteList = [];
46 * The list of available sinks.
47 * @type {!Array<!media_router.Sink>}
49 var fakeSinkList = [];
52 * The list of elements to check for visibility.
53 * @const {!Array<string>}
55 var hiddenCheckElementIdList = [
56 'cast-mode-header-text',
63 'sink-list-header-text',
67 // Checks whether the current icon matches the icon used for the view.
68 var checkArrowDropIcon = function(view) {
69 assertEquals(container.computeArrowDropIcon_(view),
70 container.$['arrow-drop-icon'].icon);
73 // Checks whether |view| matches the current view of |container|.
74 var checkCurrentView = function(view) {
75 assertEquals(view, container.currentView_);
78 // Checks whether the elements specified in |elementIdList| are visible.
79 // Checks whether all other elements are hidden.
80 var checkElementsVisibleWithId = function(elementIdList) {
81 for (var i = 0; i < elementIdList.length; i++)
82 checkElementHidden(false, container.$[elementIdList[i]]);
84 for (var j = 0; j < hiddenCheckElementIdList.length; j++) {
85 if (elementIdList.indexOf(hiddenCheckElementIdList[j]) == -1)
86 checkElementHidden(true, container.$[hiddenCheckElementIdList[j]]);
90 // Checks whether |element| is hidden.
91 var checkElementHidden = function(hidden, element) {
92 assertEquals(hidden, element.hidden);
95 // Checks whether |expected| and the text in the |elementId| element
97 var checkElementText = function(expected, element) {
98 assertEquals(expected.trim(), element.textContent.trim());
101 // Checks whether |expected| and the text in the |elementId| element
102 // are equal given an id.
103 var checkElementTextWithId = function(expected, elementId) {
104 checkElementText(expected, container.$[elementId]);
107 // Import media_router_container.html before running suite.
108 suiteSetup(function() {
109 return PolymerTest.importHtml(
110 'chrome://media-router/elements/media_router_container/' +
111 'media_router_container.html');
114 // Initialize a media-router-container before each test.
115 setup(function(done) {
116 PolymerTest.clearBody();
117 container = document.createElement('media-router-container');
118 document.body.appendChild(container);
120 // Initialize local variables.
122 new media_router.CastMode(0, 'Description 0', 'google.com'),
123 new media_router.CastMode(1, 'Description 1', null),
124 new media_router.CastMode(2, 'Description 2', null),
127 fakeCastModeListWithNonDefaultModesOnly = [
128 new media_router.CastMode(1, 'Description 1', null),
129 new media_router.CastMode(2, 'Description 2', null),
130 new media_router.CastMode(3, 'Description 3', null),
134 new media_router.Route('id 1', 'sink id 1', 'Title 1', 0, true),
135 new media_router.Route('id 2', 'sink id 2', 'Title 2', 1, false),
138 fakeRouteListWithLocalRoutesOnly = [
139 new media_router.Route('id 1', 'sink id 1', 'Title 1', 0, true),
140 new media_router.Route('id 2', 'sink id 2', 'Title 2', 1, true),
144 new media_router.Sink('sink id 1', 'Sink 1',
145 media_router.SinkIconType.CAST,
146 media_router.SinkStatus.ACTIVE, [1, 2, 3]),
147 new media_router.Sink('sink id 2', 'Sink 2',
148 media_router.SinkIconType.CAST,
149 media_router.SinkStatus.ACTIVE, [1, 2, 3]),
150 new media_router.Sink('sink id 3', 'Sink 3',
151 media_router.SinkIconType.CAST,
152 media_router.SinkStatus.PENDING, [1, 2, 3]),
155 fakeBlockingIssue = new media_router.Issue(
156 'issue id 1', 'Issue Title 1', 'Issue Message 1', 0, 1,
157 'route id 1', true, 1234);
159 fakeNonBlockingIssue = new media_router.Issue(
160 'issue id 2', 'Issue Title 2', 'Issue Message 2', 0, 1,
161 'route id 2', false, 1234);
163 // Allow for the media router container to be created and attached.
167 // Tests for 'close-button-click' event firing when the close button
169 test('close button click', function(done) {
170 container.addEventListener('close-button-click', function() {
173 MockInteractions.tap(container.$['close-button']);
176 // Tests for 'create-route' event firing when a sink with no associated
178 test('select sink without a route', function(done) {
179 container.sinkList = fakeSinkList;
181 setTimeout(function() {
183 container.$['sink-list'].querySelectorAll('paper-item');
185 container.addEventListener('create-route', function(data) {
186 assertEquals(fakeSinkList[2].id, data.detail.sinkId);
187 assertEquals(container.selectedCastModeValue_,
188 data.detail.selectedCastModeValue);
192 // Tap on a sink without a route, which should fire a 'create-route'
194 MockInteractions.tap(sinkList[2]);
198 // Tests that selecting a sink with an associated route will make the
199 // |container| switch to ROUTE_DETAILS view.
200 test('select sink with a route', function(done) {
201 container.sinkList = fakeSinkList;
202 container.routeList = fakeRouteList;
204 setTimeout(function() {
206 container.$['sink-list'].querySelectorAll('paper-item');
208 // Start from the SINK_LIST view.
209 container.showSinkList_();
210 checkCurrentView(container.CONTAINER_VIEW_.SINK_LIST);
211 MockInteractions.tap(sinkList[0]);
212 checkCurrentView(container.CONTAINER_VIEW_.ROUTE_DETAILS);
217 // Tests that |container| returns to SINK_LIST view and arrow drop icon
218 // toggles after a cast mode is selected.
219 test('select cast mode', function(done) {
220 container.castModeList = fakeCastModeListWithNonDefaultModesOnly;
222 MockInteractions.tap(container.$['arrow-drop-icon']);
223 checkArrowDropIcon(container.CONTAINER_VIEW_.CAST_MODE_LIST);
224 checkCurrentView(container.CONTAINER_VIEW_.CAST_MODE_LIST);
226 setTimeout(function() {
228 container.$['cast-mode-list'].querySelectorAll('paper-item');
230 MockInteractions.tap(castModeList[2]);
231 checkArrowDropIcon(container.CONTAINER_VIEW_.SINK_LIST);
232 checkCurrentView(container.CONTAINER_VIEW_.SINK_LIST);
237 // Tests that clicking on the drop down icon will toggle |container|
238 // between SINK_LIST and CAST_MODE_LIST views.
239 test('click drop down icon', function() {
240 checkCurrentView(container.CONTAINER_VIEW_.SINK_LIST);
242 MockInteractions.tap(container.$['arrow-drop-icon']);
243 checkArrowDropIcon(container.CONTAINER_VIEW_.CAST_MODE_LIST);
244 checkCurrentView(container.CONTAINER_VIEW_.CAST_MODE_LIST);
246 MockInteractions.tap(container.$['arrow-drop-icon']);
247 checkArrowDropIcon(container.CONTAINER_VIEW_.SINK_LIST);
248 checkCurrentView(container.CONTAINER_VIEW_.SINK_LIST);
251 // Tests the |computeArrowDropIcon_| function.
252 test('compute arrow drop icon', function() {
253 assertEquals('arrow-drop-up',
254 container.computeArrowDropIcon_(
255 container.CONTAINER_VIEW_.CAST_MODE_LIST));
256 assertEquals('arrow-drop-down',
257 container.computeArrowDropIcon_(
258 container.CONTAINER_VIEW_.ROUTE_DETAILS));
259 assertEquals('arrow-drop-down',
260 container.computeArrowDropIcon_(
261 container.CONTAINER_VIEW_.SINK_LIST));
264 // Tests the header text. Choosing a cast mode updates the header text.
265 test('header text with no default cast modes', function(done) {
266 checkElementTextWithId(loadTimeData.getString('selectCastModeHeader'),
267 'cast-mode-header-text');
269 var fakeHeaderText = 'fake header text';
270 container.headerText = fakeHeaderText;
271 checkElementTextWithId(fakeHeaderText, 'sink-list-header-text');
273 // Set the cast mode list to update the header text when one is
275 container.castModeList = fakeCastModeListWithNonDefaultModesOnly;
277 setTimeout(function() {
279 container.$['cast-mode-list'].querySelectorAll('paper-item');
281 for (var i = 0; i < fakeCastModeListWithNonDefaultModesOnly.length;
283 MockInteractions.tap(castModeList[i]);
284 checkElementTextWithId(
285 fakeCastModeListWithNonDefaultModesOnly[i].description,
286 'sink-list-header-text');
288 fakeCastModeListWithNonDefaultModesOnly[i].description,
296 // Tests the header text when updated with a cast mode list with a mix of
297 // default and non-default cast modes.
298 test('cast modes with one default mode', function(done) {
299 container.castModeList = fakeCastModeList;
301 setTimeout(function() {
303 container.$['cast-mode-list'].querySelectorAll('paper-item');
305 for (var i = 0; i < fakeCastModeList.length; i++) {
306 MockInteractions.tap(castModeList[i]);
307 if (fakeCastModeList[i].type == media_router.CastModeType.DEFAULT) {
308 checkElementTextWithId(fakeCastModeList[i].description,
309 'sink-list-header-text');
310 checkElementText(fakeCastModeList[i].host,
313 checkElementTextWithId(fakeCastModeList[i].description,
314 'sink-list-header-text');
315 checkElementText(fakeCastModeList[i].description,
324 // Tests that text shown for each sink matches their names.
325 test('sink list text', function(done) {
326 container.sinkList = fakeSinkList;
328 setTimeout(function() {
330 container.$['sink-list'].querySelectorAll('paper-item');
332 for (var i = 0; i < fakeSinkList.length; i++) {
333 checkElementText(fakeSinkList[i].name, sinkList[i]);
339 // Tests the text shown for the sink list.
340 test('initial sink list route text', function(done) {
341 container.sinkList = fakeSinkList;
342 container.routeList = fakeRouteList;
344 setTimeout(function() {
346 container.$['sink-list'].querySelectorAll('.route');
348 checkElementText(fakeRouteList[0].description, routeList[0]);
349 checkElementText(fakeRouteList[1].description, routeList[1]);
350 checkElementText('', routeList[2]);
355 // Tests the visibility of routes in the sink list.
356 test('initial route visibility', function(done) {
357 container.sinkList = fakeSinkList;
358 container.routeList = fakeRouteList;
360 setTimeout(function() {
362 container.$['sink-list'].querySelectorAll('.route');
364 checkElementHidden(false, routeList[0]);
365 checkElementHidden(false, routeList[1]);
366 checkElementHidden(true, routeList[2]);
371 // Tests the expected view when there is only one local active route and
372 // media_router_container is created for the first time.
373 test('initial view with one local route', function() {
374 container.sinkList = fakeSinkList;
375 container.routeList = fakeRouteList;
377 checkCurrentView(container.CONTAINER_VIEW_.ROUTE_DETAILS);
380 // Tests the expected view when there are multiple local active routes
381 // and media_router_container is created for the first time.
382 test('initial view with multiple local routes', function() {
383 container.sinkList = fakeSinkList;
384 container.routeList = fakeRouteListWithLocalRoutesOnly;
386 checkCurrentView(container.CONTAINER_VIEW_.SINK_LIST);
389 // Tests the expected view when there are no local active routes and
390 // media_router_container is created for the first time.
391 test('initial view with one local route', function() {
392 container.sinkList = fakeSinkList;
393 container.routeList = [];
395 checkCurrentView(container.CONTAINER_VIEW_.SINK_LIST);
398 // Tests for expected visible UI when the view is CAST_MODE_LIST.
399 test('cast mode list state visibility', function() {
400 container.showCastModeList_();
401 checkElementsVisibleWithId(['cast-mode-header-text',
407 // Set a non-blocking issue. The issue should stay hidden.
408 container.issue = fakeNonBlockingIssue;
409 checkElementsVisibleWithId(['cast-mode-header-text',
415 // Set a blocking issue. The issue should stay hidden.
416 container.issue = fakeBlockingIssue;
417 checkElementsVisibleWithId(['cast-mode-header-text',
424 // Tests for expected visible UI when the view is ROUTE_DETAILS.
425 test('route details state visibility', function() {
426 container.showRouteDetails_();
427 checkElementsVisibleWithId(['device-missing',
431 // Set a non-blocking issue. The issue should be shown.
432 container.issue = fakeNonBlockingIssue;
433 checkElementsVisibleWithId(['device-missing',
438 // Set a blocking issue. The issue should be shown, and everything
440 container.issue = fakeBlockingIssue;
441 checkElementsVisibleWithId(['device-missing',
446 // Tests for expected visible UI when the view is SINK_LIST.
447 test('sink list state visibility', function() {
448 container.showSinkList_();
449 checkElementsVisibleWithId(['container-header',
452 'sink-list-header-text',
455 // Set an non-empty sink list.
456 container.sinkList = fakeSinkList;
457 checkElementsVisibleWithId(['container-header',
459 'sink-list-header-text',
462 // Set a non-blocking issue. The issue should be shown.
463 container.issue = fakeNonBlockingIssue;
464 checkElementsVisibleWithId(['container-header',
467 'sink-list-header-text',
470 // Set a blocking issue. The issue should be shown, and everything
472 container.issue = fakeBlockingIssue;
473 checkElementsVisibleWithId(['issue-banner', 'sink-list']);
479 registerTests: registerTests,