Commit 046a6b4f authored by yoshiki@chromium.org's avatar yoshiki@chromium.org

[VideoPlayer] Browser tests for new separated video player app

BUG=357621
TEST=manually tested

R=hirono@chromium.org
TBR=arv@chromium.org
# TBRing for adding a resource.

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260198 0039d316-1c4b-4281-b951-d872f2087c98
parent ac8a3642
......@@ -735,6 +735,13 @@ INSTANTIATE_TEST_CASE_P(
// http://crbug.com/348008
// DISABLED TestParameter(NOT_IN_GUEST_MODE, "zipOpenDrive")));
INSTANTIATE_TEST_CASE_P(
OpenVideoFiles,
FileManagerBrowserTest,
::testing::Values(TestParameter(IN_GUEST_MODE, "videoOpenDownloads"),
TestParameter(NOT_IN_GUEST_MODE, "videoOpenDownloads"),
TestParameter(NOT_IN_GUEST_MODE, "videoOpenDrive")));
INSTANTIATE_TEST_CASE_P(
OpenAudioFiles,
FileManagerBrowserTest,
......
......@@ -75,6 +75,8 @@
<include name="IDR_VIDEO_PLAYER" file="video_player/video_player.html" allowexternalscript="true" flattenhtml="true" type="BINDATA" />
<include name="IDR_VIDEO_PLAYER_JS" file="video_player/js/video_player_scripts.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_VIDEO_PLAYER_BKGND_JS" file="video_player/js/background.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_VIDEO_PLAYER_TEST_UTIL_JS" file="video_player/js/test_util.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_VIDEO_PLAYER_ERROR_UTIL_JS" file="video_player/js/error_util.js" flattenhtml="false" type="BINDATA" />
<include name="IDR_VIDEO_PLAYER_ICON_16" file="video_player/images/100/icon.png" type="BINDATA" />
<include name="IDR_VIDEO_PLAYER_ICON_32" file="video_player/images/200/icon.png" type="BINDATA" />
<include name="IDR_FILE_MANAGER_AUDIO_PLAYER" file="file_manager/audio_player.html" allowexternalscript="true" flattenhtml="true" type="BINDATA" />
......
......@@ -4,6 +4,12 @@
'use strict';
// Stores the app windows OLNY for test purpose.
// We SHOULD NOT use it as it is except for test, since the files which have
// the same name will be overridden each other.
var appWindowsForTest = {};
chrome.app.runtime.onLaunched.addListener(function(launchData) {
if (!launchData || !launchData.items || launchData.items.length == 0)
return;
......@@ -12,11 +18,12 @@ chrome.app.runtime.onLaunched.addListener(function(launchData) {
entry.file(function(file) {
var url = window.URL.createObjectURL(file);
open(url, entry.name);
}, function() {
}.wrap(),
function() {
// TODO(yoshiki): handle error in a smarter way.
open('', 'error'); // Empty URL shows the error message.
});
});
}.wrap());
}.wrap());
function open(url, title) {
chrome.app.window.create('video_player.html', {
......@@ -26,8 +33,11 @@ function open(url, title) {
minHeight: 100
},
function(createdWindow) {
// Stores the window for test purpose.
appWindowsForTest[title] = createdWindow;
createdWindow.setIcon('images/200/icon.png');
createdWindow.contentWindow.videoUrl = url;
createdWindow.contentWindow.videoTitle = title;
});
}.wrap());
}
// Copyright 2014 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.
'use strict';
/**
* This variable is checked in SelectFileDialogExtensionBrowserTest.
* @type {number}
*/
window.JSErrorCount = 0;
/**
* Counts uncaught exceptions.
*/
window.onerror = function() { window.JSErrorCount++; };
/**
* Wraps the function to use it as a callback.
* This does:
* - Capture the stack trace in case of error.
* - Bind this object
*
* @param {Object} thisObject Object to be used as this.
* @return {function} Wapped function.
*/
Function.prototype.wrap = function(thisObject) {
var func = this;
var liveStack = (new Error('Stack trace before async call')).stack;
if (thisObject === undefined)
thisObject = null;
return function wrappedCallback() {
try {
return func.apply(thisObject, arguments);
} catch (e) {
console.error('Exception happens in callback.', liveStack);
window.JSErrorCount++;
throw e;
}
}
};
// Copyright 2014 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.
/**
* Namespace for test related things.
*/
var test = test || {};
/**
* Namespace for test utility functions.
*
* Public functions in the test.util.sync and the test.util.async namespaces are
* published to test cases and can be called by using callRemoteTestUtil. The
* arguments are serialized as JSON internally. If application ID is passed to
* callRemoteTestUtil, the content window of the application is added as the
* first argument. The functions in the test.util.async namespace are passed the
* callback function as the last argument.
*/
test.util = {};
/**
* Namespace for synchronous utility functions.
*/
test.util.sync = {};
/**
* Namespace for asynchronous utility functions.
*/
test.util.async = {};
/**
* Extension ID of the testing extension.
* @type {string}
* @const
*/
test.util.TESTING_EXTENSION_ID = 'oobinhbdbiehknkpbpejbbpdbkdjmoco';
/**
* Opens the main Files.app's window and waits until it is ready.
*
* @param {Window} contentWindow Video player window to be chacked toOB.
* @return {boolean} True if the video is playing, false otherwise.
*/
test.util.sync.isPlaying = function(contentWindow) {
var selector = 'video[src]';
var element = contentWindow.document.querySelector(selector);
if (!element)
return false;
return !element.paused;
};
/**
* Gets total Javascript error count from each app window.
* @return {number} Error count.
*/
test.util.sync.getErrorCount = function() {
var totalCount = JSErrorCount;
for (var appId in appWindowsForTest) {
var contentWindow = appWindowsForTest[appId].contentWindow;
if (contentWindow.JSErrorCount)
totalCount += contentWindow.JSErrorCount;
}
// Errors in the background page.
totalCount += window.JSErrorCount;
return totalCount;
};
/**
* Registers message listener, which runs test utility functions.
*/
test.util.registerRemoteTestUtils = function() {
// Register the message listener.
var onMessage = chrome.runtime ? chrome.runtime.onMessageExternal :
chrome.extension.onMessageExternal;
// Return true for asynchronous functions and false for synchronous.
onMessage.addListener(function(request, sender, sendResponse) {
// Check the sender.
if (sender.id != test.util.TESTING_EXTENSION_ID) {
console.error('The testing extension must be white-listed.');
sendResponse(false);
return false;
}
if (!request.func || request.func[request.func.length - 1] == '_') {
request.func = '';
}
// Prepare arguments.
var args = request.args.slice(); // shallow copy
if (request.file) {
if (!appWindowsForTest[request.file]) {
console.error('Specified window not found: ' + request.file);
sendResponse(false);
return false;
}
args.unshift(appWindowsForTest[request.file].contentWindow);
}
// Call the test utility function and respond the result.
if (test.util.async[request.func]) {
args[test.util.async[request.func].length - 1] = function() {
console.debug('Received the result of ' + request.func);
sendResponse.apply(null, arguments);
};
console.debug('Waiting for the result of ' + request.func);
test.util.async[request.func].apply(null, args);
return true;
} else if (test.util.sync[request.func]) {
sendResponse(test.util.sync[request.func].apply(null, args));
return false;
} else {
console.error('Invalid function name.');
sendResponse(false);
return false;
}
}.wrap());
};
// Register the test utils.
test.util.registerRemoteTestUtils();
......@@ -50,14 +50,14 @@ function FullWindowVideoControls(
VideoControls.call(this,
controlsContainer,
onPlaybackError,
loadTimeData.getString.bind(loadTimeData),
this.toggleFullScreen_.bind(this),
loadTimeData.getString.wrap(loadTimeData),
this.toggleFullScreen_.wrap(this),
videoContainer);
this.playerContainer_ = playerContainer;
this.updateStyle();
window.addEventListener('resize', this.updateStyle.bind(this));
window.addEventListener('resize', this.updateStyle.wrap(this));
document.addEventListener('keydown', function(e) {
if (e.keyIdentifier == 'U+0020') { // Space
......@@ -70,7 +70,7 @@ function FullWindowVideoControls(
false); // Leave the full screen mode.
e.preventDefault();
}
}.bind(this));
}.wrap(this));
// TODO(mtomasz): Simplify. crbug.com/254318.
videoContainer.addEventListener('click', function(e) {
......@@ -81,7 +81,7 @@ function FullWindowVideoControls(
} else {
this.togglePlayStateWithFeedback();
}
}.bind(this));
}.wrap(this));
this.inactivityWatcher_ = new MouseInactivityWatcher(playerContainer);
this.__defineGetter__('inactivityWatcher', function() {
......
......@@ -8,6 +8,8 @@
// included file but that's all right since any javascript file should start
// with a copyright comment anyway.
//<include src="error_util.js"/>
//<include src="../../../../../ui/webui/resources/js/cr.js"/>
//<include src="../../../../../ui/webui/resources/js/load_time_data.js"/>
......
......@@ -47,6 +47,8 @@
"app": {
"background": {
"scripts": [
"js/error_util.js",
"js/test_util.js",
"js/background.js"
]
},
......
......@@ -20,6 +20,7 @@
"navigation_list.js",
"open_audio_files.js",
"open_special_types.js",
"open_video_files.js",
"restore_geometry.js",
"restore_prefs.js",
"share_dialog.js",
......
// Copyright 2014 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.
'use strict';
(function() {
/**
* Extension ID of Video Player.
* @type {string}
* @const
*/
var VIDEO_PLAYER_EXTENSIONS_ID = 'jcgeabjmjgoblfofpppfkcoakmfobdko';
/**
* Calls a remote test util in video player. See: test_util.js.
*
* @param {string} func Function name.
* @param {?string} filename Target window's file name,
* @param {Array.<*>} args Array of arguments.
* @param {function(*)=} opt_callback Callback handling the function's result.
* @return {Promise} Promise to be fulfilled with the result of the remote
* utility.
*/
function callRemoteTestUtilInVideoPlayer(func, filename, args, opt_callback) {
return new Promise(function(onFulfilled) {
chrome.runtime.sendMessage(
VIDEO_PLAYER_EXTENSIONS_ID, {
func: func,
file: filename,
args: args
},
function() {
if (opt_callback)
opt_callback.apply(null, arguments);
onFulfilled(arguments[0]);
});
}).catch(function(err) {
console.log('Error in calling sendMessage: ' + (err.message || err));
return Promise.resolve(false);
});
}
/**
* Waits until a window having the given filename appears.
* @param {string} filename Filename of the requested window.
* @param {Promise} promise Promise to be fulfilled with a found window's ID.
*/
function waitForPlaying(filename) {
return repeatUntil(function() {
return callRemoteTestUtilInVideoPlayer('isPlaying',
filename,
[]).
then(function(result) {
if (result)
return true;
return pending('Window with the prefix %s is not found.', filename);
});
});
}
/**
* Tests if the video player shows up for the selected movie and that it is
* loaded successfully.
*
* @param {string} path Directory path to be tested.
*/
function videoOpen(path) {
var appId;
StepsRunner.run([
function() {
setupAndWaitUntilReady(null, path, this.next);
},
function(inAppId) {
appId = inAppId;
// Select the song.
callRemoteTestUtil(
'openFile', appId, ['world.ogv'], this.next);
},
function(result) {
chrome.test.assertTrue(result);
// Wait for the video player.
waitForPlaying('world.ogv').then(this.next);
},
function(result) {
chrome.test.assertTrue(result);
callRemoteTestUtilInVideoPlayer(
'getErrorCount', null, [], this.next);
},
function(errorCount) {
chrome.test.assertEq(errorCount, 0);
checkIfNoErrorsOccured(this.next);
}
]);
}
// Exports test functions.
testcase.videoOpenDrive = function() {
videoOpen(RootPath.DRIVE);
};
testcase.videoOpenDownloads = function() {
videoOpen(RootPath.DOWNLOADS);
};
})();
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