| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'chrome://tab-strip/tab.js'; |
| |
| import {getFavicon, getFaviconForPageURL} from 'chrome://resources/js/icon.m.js'; |
| import {TabNetworkState, TabsApiProxy} from 'chrome://tab-strip/tabs_api_proxy.js'; |
| |
| import {TestTabsApiProxy} from './test_tabs_api_proxy.js'; |
| |
| suite('Tab', function() { |
| let testTabsApiProxy; |
| let tabElement; |
| |
| const tab = { |
| id: 1001, |
| networkState: TabNetworkState.NONE, |
| title: 'My title', |
| }; |
| |
| setup(() => { |
| document.body.innerHTML = ''; |
| |
| testTabsApiProxy = new TestTabsApiProxy(); |
| TabsApiProxy.instance_ = testTabsApiProxy; |
| |
| tabElement = document.createElement('tabstrip-tab'); |
| tabElement.tab = tab; |
| document.body.appendChild(tabElement); |
| }); |
| |
| test('slideIn animates in the element', async () => { |
| const animationPromise = tabElement.slideIn(); |
| // Before animation completes |
| assertEquals('0', window.getComputedStyle(tabElement).opacity); |
| assertEquals('0px', window.getComputedStyle(tabElement).maxWidth); |
| await animationPromise; |
| // After animation completes |
| assertEquals('1', window.getComputedStyle(tabElement).opacity); |
| assertEquals('280px', window.getComputedStyle(tabElement).maxWidth); |
| }); |
| |
| test('slideOut animates out the element', async () => { |
| const animationPromise = tabElement.slideOut(); |
| // Before animation completes |
| assertEquals('1', window.getComputedStyle(tabElement).opacity); |
| assertEquals('280px', window.getComputedStyle(tabElement).maxWidth); |
| await animationPromise; |
| // After animation completes |
| assertFalse(document.body.contains(tabElement)); |
| }); |
| |
| test('toggles an [active] attribute when active', () => { |
| tabElement.tab = Object.assign({}, tab, {active: true}); |
| assertTrue(tabElement.hasAttribute('active')); |
| tabElement.tab = Object.assign({}, tab, {active: false}); |
| assertFalse(tabElement.hasAttribute('active')); |
| }); |
| |
| test('toggles a [pinned] attribute when pinned', () => { |
| tabElement.tab = Object.assign({}, tab, {pinned: true}); |
| assertTrue(tabElement.hasAttribute('pinned')); |
| tabElement.tab = Object.assign({}, tab, {pinned: false}); |
| assertFalse(tabElement.hasAttribute('pinned')); |
| }); |
| |
| test('toggles a [loading] attribute when loading', () => { |
| tabElement.tab = |
| Object.assign({}, tab, {networkState: TabNetworkState.LOADING}); |
| assertTrue(tabElement.hasAttribute('loading')); |
| tabElement.tab = |
| Object.assign({}, tab, {networkState: TabNetworkState.NONE}); |
| assertFalse(tabElement.hasAttribute('loading')); |
| }); |
| |
| test('toggles a [waiting] attribute when waiting', () => { |
| tabElement.tab = |
| Object.assign({}, tab, {networkState: TabNetworkState.WAITING}); |
| assertTrue(tabElement.hasAttribute('waiting')); |
| tabElement.tab = |
| Object.assign({}, tab, {networkState: TabNetworkState.NONE}); |
| assertFalse(tabElement.hasAttribute('waiting')); |
| }); |
| |
| test('clicking on the element activates the tab', () => { |
| tabElement.click(); |
| return testTabsApiProxy.whenCalled('activateTab', tabId => { |
| assertEquals(tabId, tab.id); |
| }); |
| }); |
| |
| test('sets the title', () => { |
| assertEquals( |
| tab.title, tabElement.shadowRoot.querySelector('#titleText').innerText); |
| }); |
| |
| test('exposes the tab ID to an attribute', () => { |
| tabElement.tab = Object.assign({}, tab, {id: 1001}); |
| assertEquals('1001', tabElement.getAttribute('data-tab-id')); |
| }); |
| |
| test('closes the tab', () => { |
| tabElement.shadowRoot.querySelector('#close').click(); |
| return testTabsApiProxy.whenCalled('closeTab').then(tabId => { |
| assertEquals(tabId, tab.id); |
| }); |
| }); |
| |
| test('sets the favicon to the favicon URL', () => { |
| const expectedFaviconUrl = 'data:mock-favicon'; |
| tabElement.tab = Object.assign({}, tab, {favIconUrl: expectedFaviconUrl}); |
| const faviconElement = tabElement.shadowRoot.querySelector('#favicon'); |
| assertEquals( |
| faviconElement.style.backgroundImage, `url("${expectedFaviconUrl}")`); |
| }); |
| |
| test('sets the favicon to the page URL if favicon URL does not exist', () => { |
| const expectedPageUrl = 'http://google.com'; |
| tabElement.tab = Object.assign({}, tab, {url: expectedPageUrl}); |
| const faviconElement = tabElement.shadowRoot.querySelector('#favicon'); |
| assertEquals( |
| faviconElement.style.backgroundImage, |
| getFaviconForPageURL(expectedPageUrl, false)); |
| }); |
| |
| test( |
| 'removes the favicon if the tab is loading and there is no favicon URL', |
| () => { |
| delete tab.favIconUrl; |
| tabElement.tab = |
| Object.assign({}, tab, {networkState: TabNetworkState.LOADING}); |
| const faviconElement = tabElement.shadowRoot.querySelector('#favicon'); |
| assertEquals(faviconElement.style.backgroundImage, 'none'); |
| }); |
| |
| test('hides the thumbnail if there is no source yet', () => { |
| const thumbnailImage = tabElement.shadowRoot.querySelector('#thumbnailImg'); |
| assertFalse(thumbnailImage.hasAttribute('src')); |
| assertEquals(window.getComputedStyle(thumbnailImage).display, 'none'); |
| }); |
| |
| test('tracks and updates the thumbnail source', async () => { |
| const requestedTabId = |
| await testTabsApiProxy.whenCalled('trackThumbnailForTab'); |
| assertEquals(requestedTabId, tab.id); |
| |
| const thumbnailSource = 'data:mock-thumbnail-source'; |
| tabElement.updateThumbnail(thumbnailSource); |
| assertEquals( |
| tabElement.shadowRoot.querySelector('#thumbnailImg').src, |
| thumbnailSource); |
| }); |
| |
| test('setting dragging state toggles an attribute', () => { |
| tabElement.setDragging(true); |
| assertTrue(tabElement.hasAttribute('dragging')); |
| tabElement.setDragging(false); |
| assertFalse(tabElement.hasAttribute('dragging')); |
| }); |
| |
| test('getting the drag image grabs the contents', () => { |
| assertEquals( |
| tabElement.getDragImage(), |
| tabElement.shadowRoot.querySelector('#dragImage')); |
| }); |
| |
| test('has custom context menu', async () => { |
| let event = new Event('contextmenu'); |
| event.clientX = 1; |
| event.clientY = 2; |
| tabElement.dispatchEvent(event); |
| |
| const contextMenuArgs = |
| await testTabsApiProxy.whenCalled('showTabContextMenu'); |
| assertEquals(contextMenuArgs[0], tabElement.tab.id); |
| assertEquals(contextMenuArgs[1], 1); |
| assertEquals(contextMenuArgs[2], 2); |
| }); |
| }); |