diff options
author | kelvinp@chromium.org <kelvinp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-14 03:09:01 +0000 |
---|---|---|
committer | kelvinp@chromium.org <kelvinp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-14 03:09:01 +0000 |
commit | e1680707bafc50eb8b878a13c3986cf214d1bcaf (patch) | |
tree | 41adc58e6df9e37f68595f728c660f00d021783f /remoting/webapp | |
parent | 257e96800fc2046f6a50b6af4b2677bdc2da5a9e (diff) | |
download | chromium_src-e1680707bafc50eb8b878a13c3986cf214d1bcaf.zip chromium_src-e1680707bafc50eb8b878a13c3986cf214d1bcaf.tar.gz chromium_src-e1680707bafc50eb8b878a13c3986cf214d1bcaf.tar.bz2 |
Cancel PIN browser test
Update PIN browser test
Invalid PIN browser test
Review URL: https://codereview.chromium.org/273753002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@270317 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/webapp')
-rw-r--r-- | remoting/webapp/base.js | 18 | ||||
-rw-r--r-- | remoting/webapp/browser_test/browser_test.js | 134 | ||||
-rw-r--r-- | remoting/webapp/browser_test/cancel_pin_browser_test.js | 46 | ||||
-rw-r--r-- | remoting/webapp/browser_test/invalid_pin_browser_test.js | 44 | ||||
-rw-r--r-- | remoting/webapp/browser_test/update_pin_browser_test.js | 109 | ||||
-rw-r--r-- | remoting/webapp/js_proto/dom_proto.js | 43 |
6 files changed, 354 insertions, 40 deletions
diff --git a/remoting/webapp/base.js b/remoting/webapp/base.js index f010d73..88c3faa 100644 --- a/remoting/webapp/base.js +++ b/remoting/webapp/base.js @@ -12,7 +12,7 @@ 'use strict'; var base = {}; -base.debug = function () {}; +base.debug = function() {}; /** * Whether to break in debugger and alert when an assertion fails. @@ -104,7 +104,7 @@ base.doNothing = function() {}; * @param {!Object} dict * @return {Array} */ -base.values = function (dict) { +base.values = function(dict) { return Object.keys(dict).map( /** @param {string} key */ function(key) { @@ -112,6 +112,20 @@ base.values = function (dict) { }); }; +base.Promise = function() {}; + +/** + * @param {number} delay + * @return {Promise} a Promise that will be fulfilled after |delay| ms. + */ +base.Promise.sleep = function(delay) { + return new Promise( + /** @param {function():void} fulfill */ + function(fulfill) { + window.setTimeout(fulfill, delay); + }); +}; + /** * A mixin for classes with events. * diff --git a/remoting/webapp/browser_test/browser_test.js b/remoting/webapp/browser_test/browser_test.js index 85985aa..7860002 100644 --- a/remoting/webapp/browser_test/browser_test.js +++ b/remoting/webapp/browser_test/browser_test.js @@ -17,17 +17,17 @@ * method. * For example: * - * browserTest.My_Test = function(myObjectLiteral) {}; - * browserTest.My_Test.prototype.run() = function() { ... }; + * browserTest.My_Test = function() {}; + * browserTest.My_Test.prototype.run(myObjectLiteral) = function() { ... }; * * The browser test is async in nature. It will keep running until * browserTest.fail("My error message.") or browserTest.pass() is called. * * For example: * - * browserTest.My_Test.prototype.run() = function() { + * browserTest.My_Test.prototype.run(myObjectLiteral) = function() { * window.setTimeout(function() { - * if (doSomething()) { + * if (doSomething(myObjectLiteral)) { * browserTest.pass(); * } else { * browserTest.fail('My error message.'); @@ -38,7 +38,7 @@ * You will then invoke the test in C++ by calling: * * RunJavaScriptTest(web_content, "My_Test", "{" - * "pin: 123123" + * "pin: '123123'" * "}"); */ @@ -57,21 +57,28 @@ browserTest.init = function() { if (result.succeeded) { console.log('Test Passed.'); } else { - console.error(result.error_message); + console.error('Test Failed.\n' + + result.error_message + '\n' + result.stack_trace); } } }; }; -browserTest.assert = function(expr, message) { +browserTest.expect = function(expr, message) { if (!expr) { message = (message) ? '<' + message + '>' : ''; - browserTest.fail('Assertion failed.' + message); + browserTest.fail('Expectation failed.' + message); } }; -browserTest.fail = function(error_message, opt_stack_trace) { - var stack_trace = opt_stack_trace || base.debug.callstack(); +browserTest.fail = function(error) { + var error_message = error; + var stack_trace = base.debug.callstack(); + + if (error instanceof Error) { + error_message = error.toString(); + stack_trace = error.stack; + } // To run browserTest locally: // 1. Go to |remoting_webapp_files| and look for @@ -100,7 +107,7 @@ browserTest.pass = function() { browserTest.clickOnControl = function(id) { var element = document.getElementById(id); - browserTest.assert(element); + browserTest.expect(element); element.click(); }; @@ -110,45 +117,96 @@ browserTest.Timeout = { DEFAULT: 5000 }; -browserTest.waitForUIMode = function(expectedMode, callback, opt_timeout) { - var uiModeChanged = remoting.testEvents.Names.uiModeChanged; - var timerId = null; - - if (opt_timeout === undefined) { - opt_timeout = browserTest.Timeout.DEFAULT; +browserTest.onUIMode = function(expectedMode, opt_timeout) { + if (expectedMode == remoting.currentMode) { + // If the current mode is the same as the expected mode, return a fulfilled + // promise. For some reason, if we fulfill the promise in the same + // callstack, V8 will assert at V8RecursionScope.h(66) with + // ASSERT(!ScriptForbiddenScope::isScriptForbidden()). + // To avoid the assert, execute the callback in a different callstack. + return base.Promise.sleep(0); } - function onTimeout() { - remoting.testEvents.removeEventListener(uiModeChanged, onUIModeChanged); - browserTest.fail('Timeout waiting for ' + expectedMode); - } + return new Promise (function(fulfill, reject) { + var uiModeChanged = remoting.testEvents.Names.uiModeChanged; + var timerId = null; + + if (opt_timeout === undefined) { + opt_timeout = browserTest.Timeout.DEFAULT; + } - function onUIModeChanged (mode) { - if (mode == expectedMode) { + function onTimeout() { remoting.testEvents.removeEventListener(uiModeChanged, onUIModeChanged); - window.clearTimeout(timerId); - timerId = null; - try { - callback(); - } catch (e) { - browserTest.fail(e.toString(), e.stack); + reject('Timeout waiting for ' + expectedMode); + } + + function onUIModeChanged(mode) { + if (mode == expectedMode) { + remoting.testEvents.removeEventListener(uiModeChanged, onUIModeChanged); + window.clearTimeout(timerId); + timerId = null; + fulfill(); } } - } - if (opt_timeout != browserTest.Timeout.NONE) { - timerId = window.setTimeout(onTimeout.bind(window, timerId), opt_timeout); - } - remoting.testEvents.addEventListener(uiModeChanged, onUIModeChanged); + if (opt_timeout != browserTest.Timeout.NONE) { + timerId = window.setTimeout(onTimeout, opt_timeout); + } + remoting.testEvents.addEventListener(uiModeChanged, onUIModeChanged); + }); +}; + +browserTest.expectMe2MeError = function(errorTag) { + var AppMode = remoting.AppMode; + var Timeout = browserTest.Timeout; + + var onConnected = browserTest.onUIMode(AppMode.IN_SESSION, Timeout.None); + var onFailure = browserTest.onUIMode(AppMode.CLIENT_CONNECT_FAILED_ME2ME); + + onConnected = onConnected.then(function() { + return Promise.reject( + 'Expected the Me2Me connection to fail.'); + }); + + onFailure = onFailure.then(function() { + var errorDiv = document.getElementById('connect-error-message'); + var actual = errorDiv.innerText; + var expected = l10n.getTranslationOrError(errorTag); + + browserTest.clickOnControl('client-finished-me2me-button'); + + if (actual != expected) { + return Promise.reject('Unexpected failure. actual:' + actual + + ' expected:' + expected); + } + }); + + return Promise.race([onConnected, onFailure]); +}; + +browserTest.expectMe2MeConnected = function() { + var AppMode = remoting.AppMode; + // Timeout if the session is not connected within 30 seconds. + var SESSION_CONNECTION_TIMEOUT = 30000; + var onConnected = browserTest.onUIMode(AppMode.IN_SESSION, + SESSION_CONNECTION_TIMEOUT); + var onFailure = browserTest.onUIMode(AppMode.CLIENT_CONNECT_FAILED_ME2ME, + browserTest.Timeout.NONE); + onFailure = onFailure.then(function() { + var errorDiv = document.getElementById('connect-error-message'); + var errorMsg = errorDiv.innerText; + return Promise.reject('Unexpected error - ' + errorMsg); + }); + return Promise.race([onConnected, onFailure]); }; browserTest.runTest = function(testClass, data) { try { - var test = new testClass(data); - browserTest.assert(typeof test.run == 'function'); - test.run(); + var test = new testClass(); + browserTest.expect(typeof test.run == 'function'); + test.run(data); } catch (e) { - browserTest.fail(e.toString(), e.stack); + browserTest.fail(e); } }; diff --git a/remoting/webapp/browser_test/cancel_pin_browser_test.js b/remoting/webapp/browser_test/cancel_pin_browser_test.js new file mode 100644 index 0000000..7ba01c7 --- /dev/null +++ b/remoting/webapp/browser_test/cancel_pin_browser_test.js @@ -0,0 +1,46 @@ +// 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. + +/** + * @fileoverview + * @suppress {checkTypes} + * Browser test for the scenario below: + * 1. Attempt to connect. + * 2. Hit cancel at the PIN prompt. + * 3. Reconnect with the PIN. + * 4. Verify that the session is connected. + */ + +'use strict'; + +/** @constructor */ +browserTest.Cancel_PIN = function() {}; + +browserTest.Cancel_PIN.prototype.run = function(data) { + browserTest.expect(typeof data.pin == 'string'); + + var AppMode = remoting.AppMode; + browserTest.clickOnControl('this-host-connect'); + browserTest.onUIMode(AppMode.CLIENT_PIN_PROMPT).then(function() { + browserTest.clickOnControl('cancel-pin-entry-button'); + return browserTest.onUIMode(AppMode.HOME); + }).then(function() { + browserTest.clickOnControl('this-host-connect'); + return browserTest.onUIMode(AppMode.CLIENT_PIN_PROMPT); + }).then( + this.enterPin_.bind(this, data.pin) + ).then(function() { + // On fulfilled. + browserTest.pass(); + }, function(reason) { + // On rejected. + browserTest.fail(reason); + }); +}; + +browserTest.Cancel_PIN.prototype.enterPin_ = function(pin) { + document.getElementById('pin-entry').value = pin; + browserTest.clickOnControl('pin-connect-button'); + return browserTest.expectMe2MeConnected(); +}; diff --git a/remoting/webapp/browser_test/invalid_pin_browser_test.js b/remoting/webapp/browser_test/invalid_pin_browser_test.js new file mode 100644 index 0000000..5cdea3e1 --- /dev/null +++ b/remoting/webapp/browser_test/invalid_pin_browser_test.js @@ -0,0 +1,44 @@ +// 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. + +/** + * @fileoverview + * @suppress {checkTypes} + * Browser test for the scenario below: + * 1. Attempt to connect. + * 2. Enter |data.pin| at the PIN prompt. + * 3. Verify that there is connection error due to invalid access code. + */ + +'use strict'; + +/** @constructor */ +browserTest.Invalid_PIN = function() {}; + +browserTest.Invalid_PIN.prototype.run = function(data) { + // Input validation. + browserTest.expect(typeof data.pin == 'string'); + + // Connect to me2me Host. + browserTest.clickOnControl('this-host-connect'); + + browserTest.onUIMode(remoting.AppMode.CLIENT_PIN_PROMPT).then( + this.enterPIN_.bind(this, data.pin) + ).then( + // Sleep for two seconds to allow the host backoff timer to reset. + base.Promise.sleep.bind(window, 2000) + ).then(function() { + // On fulfilled. + browserTest.pass(); + }, function(reason) { + // On rejected. + browserTest.fail(reason); + }); +}; + +browserTest.Invalid_PIN.prototype.enterPIN_ = function(pin) { + document.getElementById('pin-entry').value = pin; + browserTest.clickOnControl('pin-connect-button'); + return browserTest.expectMe2MeError(remoting.Error.INVALID_ACCESS_CODE); +}; diff --git a/remoting/webapp/browser_test/update_pin_browser_test.js b/remoting/webapp/browser_test/update_pin_browser_test.js new file mode 100644 index 0000000..0d0eba5 --- /dev/null +++ b/remoting/webapp/browser_test/update_pin_browser_test.js @@ -0,0 +1,109 @@ +// 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. + +/** + * @fileoverview + * @suppress {checkTypes} + * Browser test for the scenario below: + * 1. Change the PIN. + * 2. Connect with the new PIN. + * 3. Verify the connection succeeded. + * 4. Disconnect and reconnect with the old PIN. + * 5. Verify the connection failed. + */ + +'use strict'; + +/** @constructor */ +browserTest.Update_PIN = function() {}; + +browserTest.Update_PIN.prototype.run = function(data) { + var LOGIN_BACKOFF_WAIT = 2000; + // Input validation + browserTest.expect(typeof data.new_pin == 'string'); + browserTest.expect(typeof data.old_pin == 'string'); + browserTest.expect(data.new_pin != data.old_pin, + 'The new PIN and the old PIN cannot be the same'); + + this.changePIN_(data.new_pin).then( + this.connect_.bind(this) + ).then( + this.enterPIN_.bind(this, data.old_pin, true /* expectError*/) + ).then( + // Sleep for two seconds to allow for the login backoff logic to reset. + base.Promise.sleep.bind(null, LOGIN_BACKOFF_WAIT) + ).then( + this.connect_.bind(this) + ).then( + this.enterPIN_.bind(this, data.new_pin, false /* expectError*/) + ).then( + // Clean up the test by disconnecting and changing the PIN back + this.disconnect_.bind(this) + ).then( + // The PIN must be restored regardless of success or failure. + this.changePIN_.bind(this, data.old_pin), + this.changePIN_.bind(this, data.old_pin) + ).then( + // On fulfilled. + browserTest.pass, + // On rejected. + browserTest.fail + ); +}; + +browserTest.Update_PIN.prototype.changePIN_ = function(newPin) { + var AppMode = remoting.AppMode; + var HOST_RESTART_WAIT = 10000; + + browserTest.clickOnControl('change-daemon-pin'); + + return browserTest.onUIMode(AppMode.HOST_SETUP_ASK_PIN).then(function() { + var onSetupDone = browserTest.onUIMode(AppMode.HOST_SETUP_DONE); + document.getElementById('daemon-pin-entry').value = newPin; + document.getElementById('daemon-pin-confirm').value = newPin; + browserTest.clickOnControl('daemon-pin-ok'); + return onSetupDone; + }).then(function() { + browserTest.clickOnControl('host-config-done-dismiss'); + // On Linux, we restart the host after changing the PIN, need to sleep + // for ten seconds before the host is ready for connection. + return base.Promise.sleep(HOST_RESTART_WAIT); + }); +}; + +browserTest.Update_PIN.prototype.connect_ = function() { + browserTest.clickOnControl('this-host-connect'); + return browserTest.onUIMode(remoting.AppMode.CLIENT_PIN_PROMPT); +}; + +browserTest.Update_PIN.prototype.disconnect_ = function() { + var AppMode = remoting.AppMode; + + remoting.disconnect(); + + return browserTest.onUIMode(AppMode.CLIENT_SESSION_FINISHED_ME2ME) + .then(function() { + var onHome = browserTest.onUIMode(AppMode.HOME); + browserTest.clickOnControl('client-finished-me2me-button'); + return onHome; + }); +}; + +browserTest.Update_PIN.prototype.enterPIN_ = function(pin, expectError) { + // Wait for 500ms before hitting the PIN button. From experiment, sometimes + // the PIN prompt does not dismiss without the timeout. + var CONNECT_PIN_WAIT = 500; + + document.getElementById('pin-entry').value = pin; + + return base.Promise.sleep(CONNECT_PIN_WAIT).then(function() { + browserTest.clickOnControl('pin-connect-button'); + }).then(function() { + if (expectError) { + return browserTest.expectMe2MeError(remoting.Error.INVALID_ACCESS_CODE); + } else { + return browserTest.expectMe2MeConnected(); + } + }); +}; diff --git a/remoting/webapp/js_proto/dom_proto.js b/remoting/webapp/js_proto/dom_proto.js index 64f330f..1e392cb 100644 --- a/remoting/webapp/js_proto/dom_proto.js +++ b/remoting/webapp/js_proto/dom_proto.js @@ -167,3 +167,46 @@ var MediaSource = function() {} * @return {SourceBuffer} */ MediaSource.prototype.addSourceBuffer = function(format) {} + +/** + * @constructor + * @param {function(function(*), function(*)) : void} init + */ +var Promise = function (init) {}; + +/** + * @param {function(*) : void} onFulfill + * @param {function(*) : void} onReject + * @return {Promise} + */ +Promise.prototype.then = function (onFulfill, onReject) {}; + +/** + * @param {function(*) : void} onReject + * @return {Promise} + */ +Promise.prototype['catch'] = function (onReject) {}; + +/** + * @param {Array.<Promise>} promises + * @return {Promise} + */ +Promise.prototype.race = function (promises) {} + +/** + * @param {Array.<Promise>} promises + * @return {Promise} + */ +Promise.prototype.all = function (promises) {}; + +/** + * @param {*} reason + * @return {Promise} + */ +Promise.reject = function (reason) {}; + +/** + * @param {*} value + * @return {Promise} + */ +Promise.resolve = function (value) {}; |