Commit 47464b35 authored by yoshiki's avatar yoshiki Committed by Commit bot

Fix potential flakiness in Files.app test

This patch makes the banner & focus code robust with promise. And make sure the banner existences before test runs.

BUG=478640
TEST=run TabindexFocusDownloads/FileManagerBrowserTest.Test/0 100 times

Review URL: https://codereview.chromium.org/1105333003

Cr-Commit-Position: refs/heads/master@{#327255}
parent 63b65fd1
...@@ -598,6 +598,9 @@ FileManager.prototype = /** @struct */ { ...@@ -598,6 +598,9 @@ FileManager.prototype = /** @struct */ {
this.initializeQueue_.add( this.initializeQueue_.add(
this.initFileSystemUI_.bind(this), this.initFileSystemUI_.bind(this),
['initAdditionalUI', 'initSettings'], 'initFileSystemUI'); ['initAdditionalUI', 'initSettings'], 'initFileSystemUI');
this.initializeQueue_.add(
this.initUIFocus_.bind(this),
['initAdditionalUI', 'initFileSystemUI'], 'initUIFocus');
// Run again just in case if all pending closures have completed and the // Run again just in case if all pending closures have completed and the
// queue has stopped and monitor the completion. // queue has stopped and monitor the completion.
...@@ -803,6 +806,17 @@ FileManager.prototype = /** @struct */ { ...@@ -803,6 +806,17 @@ FileManager.prototype = /** @struct */ {
callback(); callback();
}; };
/**
* One-time initialization of focus. This should run at the last of UI
* initialization.
*
* @private
*/
FileManager.prototype.initUIFocus_ = function(callback) {
this.ui_.initUIFocus();
callback();
};
/** /**
* One-time initialization of import history observer. Provides * One-time initialization of import history observer. Provides
* the glue that updates the UI when history changes. * the glue that updates the UI when history changes.
......
...@@ -42,20 +42,24 @@ function Banners( ...@@ -42,20 +42,24 @@ function Banners(
chrome.storage.onChanged.addListener(this.onStorageChange_.bind(this)); chrome.storage.onChanged.addListener(this.onStorageChange_.bind(this));
this.welcomeHeaderCounter_ = WELCOME_HEADER_COUNTER_LIMIT; this.welcomeHeaderCounter_ = WELCOME_HEADER_COUNTER_LIMIT;
this.warningDismissedCounter_ = 0; this.warningDismissedCounter_ = 0;
chrome.storage.local.get(
[WELCOME_HEADER_COUNTER_KEY, WARNING_DISMISSED_KEY], this.ready_ = new Promise(function(resolve, reject) {
function(values) { chrome.storage.local.get(
this.welcomeHeaderCounter_ = [WELCOME_HEADER_COUNTER_KEY, WARNING_DISMISSED_KEY],
parseInt(values[WELCOME_HEADER_COUNTER_KEY], 10) || 0; function(values) {
this.warningDismissedCounter_ = this.welcomeHeaderCounter_ =
parseInt(values[WARNING_DISMISSED_KEY], 10) || 0; parseInt(values[WELCOME_HEADER_COUNTER_KEY], 10) || 0;
this.warningDismissedCounter_ =
// If it's in test, override the counter to show the header by force. parseInt(values[WARNING_DISMISSED_KEY], 10) || 0;
if (window.IN_TEST) {
this.welcomeHeaderCounter_ = 0; // If it's in test, override the counter to show the header by force.
this.warningDismissedCounter_ = 0; if (chrome.test) {
} this.welcomeHeaderCounter_ = 0;
}.bind(this)); this.warningDismissedCounter_ = 0;
}
resolve();
}.bind(this));
}.bind(this));
// Authentication failed banner. // Authentication failed banner.
this.authFailedBanner_ = this.authFailedBanner_ =
...@@ -301,73 +305,76 @@ Banners.prototype.closeWelcomeBanner_ = function() { ...@@ -301,73 +305,76 @@ Banners.prototype.closeWelcomeBanner_ = function() {
* @private * @private
*/ */
Banners.prototype.checkSpaceAndMaybeShowWelcomeBanner_ = function() { Banners.prototype.checkSpaceAndMaybeShowWelcomeBanner_ = function() {
if (!this.isOnCurrentProfileDrive()) { this.ready_.then(function() {
// We are not on the drive file system. Do not show (close) the welcome if (!this.isOnCurrentProfileDrive()) {
// banner. // We are not on the drive file system. Do not show (close) the welcome
this.cleanupWelcomeBanner_(); // banner.
this.previousDirWasOnDrive_ = false; this.cleanupWelcomeBanner_();
return; this.previousDirWasOnDrive_ = false;
} return;
}
var driveVolume = this.volumeManager_.getCurrentProfileVolumeInfo( var driveVolume = this.volumeManager_.getCurrentProfileVolumeInfo(
VolumeManagerCommon.VolumeType.DRIVE); VolumeManagerCommon.VolumeType.DRIVE);
if (this.welcomeHeaderCounter_ >= WELCOME_HEADER_COUNTER_LIMIT || if (this.welcomeHeaderCounter_ >= WELCOME_HEADER_COUNTER_LIMIT ||
!driveVolume || driveVolume.error) { !driveVolume || driveVolume.error) {
// The banner is already shown enough times or the drive FS is not mounted. // The banner is already shown enough times or the drive FS is not
// So, do nothing here. // mounted. So, do nothing here.
return; return;
} }
if (!this.showOffers_ || !this.showWelcome_) { if (!this.showOffers_ || !this.showWelcome_) {
// Because it is not necessary to show the offer, set // Because it is not necessary to show the offer, set
// |usePromoWelcomeBanner_| false here. Note that it probably should be able // |usePromoWelcomeBanner_| false here. Note that it probably should be
// to do this in the constructor, but there remains non-trivial path, // able to do this in the constructor, but there remains non-trivial path,
// which may be causes |usePromoWelcomeBanner_| == true's behavior even // which may be causes |usePromoWelcomeBanner_| == true's behavior even
// if |showOffers_| is false. // if |showOffers_| is false.
// TODO(hidehiko): Make sure if it is expected or not, and simplify // TODO(hidehiko): Make sure if it is expected or not, and simplify
// |showOffers_| if possible. // |showOffers_| if possible.
this.usePromoWelcomeBanner_ = false; this.usePromoWelcomeBanner_ = false;
} }
// Perform asynchronous tasks in parallel. // Choose the offer basing on the board name. The default one is 100 GB.
var group = new AsyncUtil.Group(); var offerSize = 100; // In GB.
var offerServiceId = 'drive.cros.echo.1';
// Choose the offer basing on the board name. The default one is 100 GB. if (util.boardIs('link')) {
var offerSize = 100; // In GB. offerSize = 1024; // 1 TB.
var offerServiceId = 'drive.cros.echo.1'; offerServiceId = 'drive.cros.echo.2';
}
if (util.boardIs('link')) { // Perform asynchronous tasks in parallel.
offerSize = 1024; // 1 TB. var group = new AsyncUtil.Group();
offerServiceId = 'drive.cros.echo.2';
}
// If the offer has been checked, then do not show the promo anymore. // If the offer has been checked, then do not show the promo anymore.
group.add(function(onCompleted) { group.add(function(onCompleted) {
chrome.echoPrivate.getOfferInfo(offerServiceId, function(offerInfo) { chrome.echoPrivate.getOfferInfo(offerServiceId, function(offerInfo) {
// If the offer has not been checked, then an error is raised. // If the offer has not been checked, then an error is raised.
if (!chrome.runtime.lastError) if (!chrome.runtime.lastError)
this.usePromoWelcomeBanner_ = false; this.usePromoWelcomeBanner_ = false;
onCompleted(); onCompleted();
}.bind(this));
}.bind(this)); }.bind(this));
}.bind(this));
if (this.usePromoWelcomeBanner_) {
// getSizeStats for Drive file system accesses to the server, so we should
// minimize the invocation.
group.add(function(onCompleted) { group.add(function(onCompleted) {
// Current directory must be set, since this code is called after if (this.usePromoWelcomeBanner_) {
// scanning is completed. However, the volumeInfo may be gone. // getSizeStats for Drive file system accesses to the server, so we
chrome.fileManagerPrivate.getSizeStats( // should minimize the invocation.
driveVolume.volumeId,
function(result) { // Current directory must be set, since this code is called after
if (result && result.totalSize >= offerSize * 1024 * 1024 * 1024) // scanning is completed. However, the volumeInfo may be gone.
this.usePromoWelcomeBanner_ = false; chrome.fileManagerPrivate.getSizeStats(
onCompleted(); driveVolume.volumeId,
}.bind(this)); function(result) {
if (result && result.totalSize >= offerSize * 1024 * 1024 * 1024)
this.usePromoWelcomeBanner_ = false;
onCompleted();
}.bind(this));
}
}.bind(this)); }.bind(this));
}
group.run(this.maybeShowWelcomeBanner_.bind(this)); group.run(this.maybeShowWelcomeBanner_.bind(this));
}.bind(this));
}; };
/** /**
...@@ -376,27 +383,29 @@ Banners.prototype.checkSpaceAndMaybeShowWelcomeBanner_ = function() { ...@@ -376,27 +383,29 @@ Banners.prototype.checkSpaceAndMaybeShowWelcomeBanner_ = function() {
* @private * @private
*/ */
Banners.prototype.maybeShowWelcomeBanner_ = function() { Banners.prototype.maybeShowWelcomeBanner_ = function() {
if (this.directoryModel_.getFileList().length == 0 && this.ready_.then(function() {
this.welcomeHeaderCounter_ == 0) { if (this.directoryModel_.getFileList().length == 0 &&
// Only show the full page banner if the header banner was never shown. this.welcomeHeaderCounter_ == 0) {
// Do not increment the counter. // Only show the full page banner if the header banner was never shown.
// The timeout below is required because sometimes another // Do not increment the counter.
// 'rescan-completed' event arrives shortly with non-empty file list. // The timeout below is required because sometimes another
setTimeout(function() { // 'rescan-completed' event arrives shortly with non-empty file list.
if (this.isOnCurrentProfileDrive() && this.welcomeHeaderCounter_ == 0) { setTimeout(function() {
this.prepareAndShowWelcomeBanner_('page', 'DRIVE_WELCOME_TEXT_LONG'); if (this.isOnCurrentProfileDrive() && this.welcomeHeaderCounter_ == 0) {
this.prepareAndShowWelcomeBanner_('page', 'DRIVE_WELCOME_TEXT_LONG');
}
}.bind(this), 2000);
} else {
// We do not want to increment the counter when the user navigates
// between different directories on Drive, but we increment the counter
// once anyway to prevent the full page banner from showing.
if (!this.previousDirWasOnDrive_ || this.welcomeHeaderCounter_ == 0) {
this.setWelcomeHeaderCounter_(this.welcomeHeaderCounter_ + 1);
this.prepareAndShowWelcomeBanner_('header', 'DRIVE_WELCOME_TEXT_SHORT');
} }
}.bind(this), 2000);
} else {
// We do not want to increment the counter when the user navigates
// between different directories on Drive, but we increment the counter
// once anyway to prevent the full page banner from showing.
if (!this.previousDirWasOnDrive_ || this.welcomeHeaderCounter_ == 0) {
this.setWelcomeHeaderCounter_(this.welcomeHeaderCounter_ + 1);
this.prepareAndShowWelcomeBanner_('header', 'DRIVE_WELCOME_TEXT_SHORT');
} }
} this.previousDirWasOnDrive_ = true;
this.previousDirWasOnDrive_ = true; }.bind(this));
}; };
/** /**
......
...@@ -314,23 +314,24 @@ FileManagerUI.prototype.initAdditionalUI = function( ...@@ -314,23 +314,24 @@ FileManagerUI.prototype.initAdditionalUI = function(
// Add handlers. // Add handlers.
document.defaultView.addEventListener('resize', this.relayout.bind(this)); document.defaultView.addEventListener('resize', this.relayout.bind(this));
};
/**
* Initializes the focus.
*/
FileManagerUI.prototype.initUIFocus = function() {
// Set the initial focus. When there is no focus, the active element is the // Set the initial focus. When there is no focus, the active element is the
// <body>. // <body>.
setTimeout(function() { var targetElement = null;
if (document.activeElement === document.body) { if (this.dialogType_ == DialogType.SELECT_SAVEAS_FILE) {
var targetElement = null; targetElement = this.dialogFooter.filenameInput;
if (this.dialogType_ == DialogType.SELECT_SAVEAS_FILE) { } else if (this.listContainer.currentListType !=
targetElement = this.dialogFooter.filenameInput; ListContainer.ListType.UNINITIALIZED) {
} else if (this.listContainer.currentListType != targetElement = this.listContainer.currentList;
ListContainer.ListType.UNINITIALIZED) { }
targetElement = this.listContainer.currentList;
} if (targetElement)
targetElement.focus();
if (targetElement)
targetElement.focus();
}
}.bind(this), 0);
}; };
/** /**
......
...@@ -66,9 +66,12 @@ testcase.tabindexFocus = function() { ...@@ -66,9 +66,12 @@ testcase.tabindexFocus = function() {
appId = inAppId; appId = inAppId;
remoteCall.waitForElement(appId, ['#file-list:focus']).then(this.next); remoteCall.waitForElement(appId, ['#file-list:focus']).then(this.next);
}, },
// Press the Tab key. function(element) {
remoteCall.waitForElement(appId, ['#drive-welcome-link']).then(this.next);
},
function(element) { function(element) {
remoteCall.callRemoteTestUtil('getActiveElement', appId, [], this.next); remoteCall.callRemoteTestUtil('getActiveElement', appId, [], this.next);
// Press the Tab key.
}, function(element) { }, function(element) {
chrome.test.assertEq('list', element.attributes['class']); chrome.test.assertEq('list', element.attributes['class']);
remoteCall.checkNextTabFocus(appId, 'search-button').then(this.next); remoteCall.checkNextTabFocus(appId, 'search-button').then(this.next);
...@@ -150,7 +153,9 @@ testcase.tabindexFocusDirectorySelected = function() { ...@@ -150,7 +153,9 @@ testcase.tabindexFocusDirectorySelected = function() {
appId = inAppId; appId = inAppId;
remoteCall.waitForElement(appId, ['#file-list:focus']).then(this.next); remoteCall.waitForElement(appId, ['#file-list:focus']).then(this.next);
}, },
// Press the Tab key. function(element) {
remoteCall.waitForElement(appId, ['#drive-welcome-link']).then(this.next);
},
function(element) { function(element) {
remoteCall.callRemoteTestUtil('getActiveElement', appId, [], this.next); remoteCall.callRemoteTestUtil('getActiveElement', appId, [], this.next);
}, function(element) { }, function(element) {
...@@ -158,6 +163,7 @@ testcase.tabindexFocusDirectorySelected = function() { ...@@ -158,6 +163,7 @@ testcase.tabindexFocusDirectorySelected = function() {
// Select the directory named 'photos'. // Select the directory named 'photos'.
remoteCall.callRemoteTestUtil( remoteCall.callRemoteTestUtil(
'selectFile', appId, ['photos']).then(this.next); 'selectFile', appId, ['photos']).then(this.next);
// Press the Tab key.
}, function(result) { }, function(result) {
chrome.test.assertTrue(result); chrome.test.assertTrue(result);
remoteCall.checkNextTabFocus(appId, 'share-button').then(this.next); remoteCall.checkNextTabFocus(appId, 'share-button').then(this.next);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment