Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(701)

Unified Diff: remoting/webapp/crd/js/host_controller_unittest.js

Issue 1065733004: Added partial unit tests for host_controller.js. More to come. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@hdf-unittest
Patch Set: added licenses to satisfy presubmit Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/webapp/crd/js/host_controller.js ('k') | remoting/webapp/crd/js/mock_host_daemon_facade.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/webapp/crd/js/host_controller_unittest.js
diff --git a/remoting/webapp/crd/js/host_controller_unittest.js b/remoting/webapp/crd/js/host_controller_unittest.js
new file mode 100644
index 0000000000000000000000000000000000000000..c62603e2c5b0e47e7cec3586b63cce2b1da05147
--- /dev/null
+++ b/remoting/webapp/crd/js/host_controller_unittest.js
@@ -0,0 +1,429 @@
+// Copyright 2015 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
+ * Unit tests for host_controller.js.
+ */
+
+(function() {
+
+'use strict';
+
+/** @type {remoting.HostController} */
+var controller;
+
+/** @type {sinon.Mock} */
+var hostListMock = null;
+
+/** @type {sinon.TestStub} */
+var generateUuidStub;
+
+/** @type {remoting.MockHostDaemonFacade} */
+var mockHostDaemonFacade;
+
+/** @type {sinon.TestStub} */
+var hostDaemonFacadeCtorStub;
+
+var FAKE_HOST_PIN = '<FAKE_HOST_PIN>';
+var FAKE_USER_EMAIL = '<FAKE_USER_EMAIL>';
+var FAKE_USER_NAME = '<FAKE_USER_NAME>';
+var FAKE_UUID = '0bad0bad-0bad-0bad-0bad-0bad0bad0bad';
+var FAKE_DAEMON_VERSION = '1.2.3.4';
+var FAKE_HOST_NAME = '<FAKE_HOST_NAME>';
+var FAKE_PUBLIC_KEY = '<FAKE_PUBLIC_KEY>';
+var FAKE_PRIVATE_KEY = '<FAKE_PRIVATE_KEY>';
+var FAKE_AUTH_CODE = '<FAKE_AUTH_CODE>';
+var FAKE_REFRESH_TOKEN = '<FAKE_REFRESH_TOKEN>';
+var FAKE_PIN_HASH = '<FAKE_PIN_HASH>';
+var FAKE_HOST_CLIENT_ID = '<FAKE_HOST_CLIENT_ID>';
+var FAKE_CLIENT_BASE_JID = '<FAKE_CLIENT_BASE_JID>';
+
+/** @type {sinon.Spy|Function} */
+var getCredentialsFromAuthCodeSpy;
+
+/** @type {sinon.Spy|Function} */
+var getPinHashSpy;
+
+/** @type {sinon.Spy|Function} */
+var startDaemonSpy;
+
+/** @type {sinon.Spy} */
+var unregisterHostByIdSpy;
+
+/** @type {sinon.Spy} */
+var onLocalHostStartedSpy;
+
+QUnit.module('host_controller', {
+ beforeEach: function(/** QUnit.Assert */ assert) {
+ chromeMocks.activate(['identity', 'runtime']);
+ chromeMocks.identity.mock$setToken('my_token');
+ remoting.identity = new remoting.Identity();
+ remoting.MockXhr.activate();
+ base.debug.assert(remoting.oauth2 === null);
+ remoting.oauth2 = new remoting.OAuth2();
+ base.debug.assert(remoting.hostList === null);
+ remoting.hostList = /** @type {remoting.HostList} */
+ (Object.create(remoting.HostList.prototype));
+
+ // When the HostList's unregisterHostById method is called, make
+ // sure the argument is correct.
+ unregisterHostByIdSpy =
+ sinon.stub(remoting.hostList, 'unregisterHostById', function(
+ /** string */ hostId) {
+ assert.equal(hostId, FAKE_UUID);
+ });
+
+ // When the HostList's onLocalHostStarted method is called, make
+ // sure the arguments are correct.
+ onLocalHostStartedSpy =
+ sinon.stub(
+ remoting.hostList, 'onLocalHostStarted', function(
+ /** string */ hostName,
+ /** string */ newHostId,
+ /** string */ publicKey) {
+ assert.equal(hostName, FAKE_HOST_NAME);
+ assert.equal(newHostId, FAKE_UUID);
+ assert.equal(publicKey, FAKE_PUBLIC_KEY);
+ });
+
+ hostDaemonFacadeCtorStub = sinon.stub(remoting, 'HostDaemonFacade');
+ mockHostDaemonFacade = new remoting.MockHostDaemonFacade();
+ hostDaemonFacadeCtorStub.returns(mockHostDaemonFacade);
+ generateUuidStub = sinon.stub(base, 'generateUuid');
+ generateUuidStub.returns(FAKE_UUID);
+ getCredentialsFromAuthCodeSpy = sinon.spy(
+ mockHostDaemonFacade, 'getCredentialsFromAuthCode');
+ getPinHashSpy = sinon.spy(mockHostDaemonFacade, 'getPinHash');
+ startDaemonSpy = sinon.spy(mockHostDaemonFacade, 'startDaemon');
+
+ // Set up successful responses from mockHostDaemonFacade.
+ // Individual tests override these values to create errors.
+ mockHostDaemonFacade.features =
+ [remoting.HostController.Feature.OAUTH_CLIENT];
+ mockHostDaemonFacade.daemonVersion = FAKE_DAEMON_VERSION;
+ mockHostDaemonFacade.hostName = FAKE_HOST_NAME;
+ mockHostDaemonFacade.privateKey = FAKE_PRIVATE_KEY;
+ mockHostDaemonFacade.publicKey = FAKE_PUBLIC_KEY;
+ mockHostDaemonFacade.hostClientId = FAKE_HOST_CLIENT_ID;
+ mockHostDaemonFacade.userEmail = FAKE_USER_EMAIL;
+ mockHostDaemonFacade.refreshToken = FAKE_REFRESH_TOKEN;
+ mockHostDaemonFacade.pinHash = FAKE_PIN_HASH;
+ mockHostDaemonFacade.startDaemonResult =
+ remoting.HostController.AsyncResult.OK;
+
+ sinon.stub(remoting.identity, 'getEmail').returns(
+ Promise.resolve(FAKE_USER_EMAIL));
+ sinon.stub(remoting.oauth2, 'getRefreshToken').returns(
+ FAKE_REFRESH_TOKEN);
+
+ controller = new remoting.HostController();
+ },
+
+ afterEach: function() {
+ controller = null;
+ getCredentialsFromAuthCodeSpy.restore();
+ generateUuidStub.restore();
+ hostDaemonFacadeCtorStub.restore();
+ remoting.hostList = null;
+ remoting.oauth2 = null;
+ remoting.MockXhr.restore();
+ chromeMocks.restore();
+ remoting.identity = null;
+ }
+});
+
+/**
+ * Install an HTTP response for requests to the registry.
+ * @param {QUnit.Assert} assert
+ * @param {boolean} withAuthCode
+ */
+function queueRegistryResponse(assert, withAuthCode) {
+ var responseJson = {
+ data: {
+ authorizationCode: FAKE_AUTH_CODE
+ }
+ };
+ if (!withAuthCode) {
+ delete responseJson.data.authorizationCode;
+ }
+
+ remoting.MockXhr.setResponseFor(
+ 'POST', 'DIRECTORY_API_BASE_URL/@me/hosts',
+ function(/** remoting.MockXhr */ xhr) {
+ assert.deepEqual(
+ xhr.params.jsonContent,
+ { data: {
+ hostId: FAKE_UUID,
+ hostName: FAKE_HOST_NAME,
+ publicKey: FAKE_PUBLIC_KEY
+ } });
+ xhr.setTextResponse(200, JSON.stringify(responseJson));
+ });
+}
+
+function mockGetClientBaseJid() {
+ sinon.stub(controller, 'getClientBaseJid_').
+ callsArgWith(0, FAKE_CLIENT_BASE_JID);
+};
+
+// Check that hasFeature returns false for missing features.
+QUnit.test('hasFeature returns false', function(assert) {
+ return new Promise(function(resolve, reject) {
+ controller.hasFeature(
+ remoting.HostController.Feature.PAIRING_REGISTRY,
+ resolve);
+ }).then(function(/** boolean */ result) {
+ assert.equal(result, false);
+ });
+});
+
+// Check that hasFeature returns true for supported features.
+QUnit.test('hasFeature returns true', function(assert) {
+ return new Promise(function(resolve, reject) {
+ controller.hasFeature(
+ remoting.HostController.Feature.OAUTH_CLIENT,
+ resolve);
+ }).then(function(/** boolean */ result) {
+ assert.equal(result, true);
+ });
+});
+
+// Check what happens when the HostDaemonFacade's getHostName method
+// fails.
+QUnit.test('start with getHostName failure', function(assert) {
+ mockHostDaemonFacade.hostName = null;
+ return new Promise(function(resolve, reject) {
+ controller.start(FAKE_HOST_PIN, true, function() {
+ reject('test failed');
+ }, function(/** remoting.Error */ e) {
+ assert.equal(e.getDetail(), 'getHostName');
+ assert.equal(e.getTag(), remoting.Error.Tag.UNEXPECTED);
+ assert.equal(unregisterHostByIdSpy.callCount, 0);
+ assert.equal(onLocalHostStartedSpy.callCount, 0);
+ assert.equal(startDaemonSpy.callCount, 0);
+ resolve(null);
+ });
+ });
+});
+
+// Check what happens when the HostDaemonFacade's generateKeyPair
+// method fails.
+QUnit.test('start with generateKeyPair failure', function(assert) {
+ mockHostDaemonFacade.publicKey = null;
+ mockHostDaemonFacade.privateKey = null;
+ return new Promise(function(resolve, reject) {
+ controller.start(FAKE_HOST_PIN, true, function() {
+ reject('test failed');
+ }, function(/** remoting.Error */ e) {
+ assert.equal(e.getDetail(), 'generateKeyPair');
+ assert.equal(e.getTag(), remoting.Error.Tag.UNEXPECTED);
+ assert.equal(unregisterHostByIdSpy.callCount, 0);
+ assert.equal(onLocalHostStartedSpy.callCount, 0);
+ assert.equal(startDaemonSpy.callCount, 0);
+ resolve(null);
+ });
+ });
+});
+
+// Check what happens when the HostDaemonFacade's getHostClientId
+// method fails.
+QUnit.test('start with getHostClientId failure', function(assert) {
+ mockHostDaemonFacade.hostClientId = null;
+ return new Promise(function(resolve, reject) {
+ controller.start(FAKE_HOST_PIN, true, function() {
+ reject('test failed');
+ }, function(/** remoting.Error */ e) {
+ assert.equal(e.getDetail(), 'getHostClientId');
+ assert.equal(e.getTag(), remoting.Error.Tag.UNEXPECTED);
+ assert.equal(unregisterHostByIdSpy.callCount, 0);
+ assert.equal(onLocalHostStartedSpy.callCount, 0);
+ assert.equal(startDaemonSpy.callCount, 0);
+ resolve(null);
+ });
+ });
+});
+
+// Check what happens when the registry returns an HTTP when we try to
+// register a host.
+QUnit.test('start with host registration failure', function(assert) {
+ remoting.MockXhr.setEmptyResponseFor(
+ 'POST', 'DIRECTORY_API_BASE_URL/@me/hosts', 500);
+ return new Promise(function(resolve, reject) {
+ controller.start(FAKE_HOST_PIN, true, function() {
+ reject('test failed');
+ }, function(/** remoting.Error */ e) {
+ assert.equal(e.getTag(), remoting.Error.Tag.REGISTRATION_FAILED);
+ assert.equal(unregisterHostByIdSpy.callCount, 0);
+ assert.equal(onLocalHostStartedSpy.callCount, 0);
+ assert.equal(startDaemonSpy.callCount, 0);
+ resolve(null);
+ });
+ });
+});
+
+// Check what happens when the HostDaemonFacade's
+// getCredentialsFromAuthCode method fails.
+QUnit.test('start with getCredentialsFromAuthCode failure', function(assert) {
+ mockHostDaemonFacade.useEmail = null;
+ mockHostDaemonFacade.refreshToken = null;
+ queueRegistryResponse(assert, true);
+ return new Promise(function(resolve, reject) {
+ controller.start(FAKE_HOST_PIN, true, function() {
+ reject('test failed');
+ }, function(/** remoting.Error */ e) {
+ assert.equal(e.getDetail(), 'getCredentialsFromAuthCode');
+ assert.equal(e.getTag(), remoting.Error.Tag.UNEXPECTED);
+ assert.equal(getCredentialsFromAuthCodeSpy.callCount, 1);
+ assert.equal(unregisterHostByIdSpy.callCount, 0);
+ assert.equal(onLocalHostStartedSpy.callCount, 0);
+ assert.equal(startDaemonSpy.callCount, 0);
+ resolve(null);
+ });
+ });
+});
+
+// Check what happens when the HostDaemonFacade's getPinHash method
+// fails, and verify that getPinHash is called when the registry
+// does't return an auth code.
+QUnit.test('start with getRefreshToken+getPinHash failure', function(assert) {
+ mockHostDaemonFacade.pinHash = null;
+ queueRegistryResponse(assert, false);
+ return new Promise(function(resolve, reject) {
+ controller.start(FAKE_HOST_PIN, true, function() {
+ reject('test failed');
+ }, function(/** remoting.Error */ e) {
+ assert.equal(e.getDetail(), 'getPinHash');
+ assert.equal(e.getTag(), remoting.Error.Tag.UNEXPECTED);
+ assert.equal(unregisterHostByIdSpy.callCount, 0);
+ assert.equal(onLocalHostStartedSpy.callCount, 0);
+ assert.equal(startDaemonSpy.callCount, 0);
+ resolve(null);
+ });
+ });
+});
+
+// Check what happens when the HostController's getClientBaseJid_
+// method fails.
+QUnit.test('start with getClientBaseJid_ failure', function(assert) {
+ queueRegistryResponse(assert, true);
+ sinon.stub(controller, 'getClientBaseJid_').
+ callsArgWith(1, remoting.Error.unexpected('getClientBaseJid_'));
+ return new Promise(function(resolve, reject) {
+ controller.start(FAKE_HOST_PIN, true, function() {
+ reject('test failed');
+ }, function(/** remoting.Error */ e) {
+ assert.equal(e.getDetail(), 'getClientBaseJid_');
+ assert.equal(e.getTag(), remoting.Error.Tag.UNEXPECTED);
+ assert.equal(unregisterHostByIdSpy.callCount, 1);
+ resolve(null);
+ });
+ });
+});
+
+// Check what happens when the HostDaemonFacade's startDaemon method
+// fails and calls its onError argument.
+QUnit.test('start with startDaemon failure', function(assert) {
+ queueRegistryResponse(assert, true);
+ mockGetClientBaseJid();
+ mockHostDaemonFacade.startDaemonResult = null;
+ return new Promise(function(resolve, reject) {
+ controller.start(FAKE_HOST_PIN, true, function() {
+ reject('test failed');
+ }, function(/** remoting.Error */ e) {
+ assert.equal(e.getDetail(), 'startDaemon');
+ assert.equal(e.getTag(), remoting.Error.Tag.UNEXPECTED);
+ assert.equal(unregisterHostByIdSpy.callCount, 1);
+ assert.equal(onLocalHostStartedSpy.callCount, 0);
+ resolve(null);
+ });
+ });
+});
+
+// Check what happens when the HostDaemonFacade's startDaemon method
+// calls is onDone method with a CANCELLED error code.
+QUnit.test('start with startDaemon cancelled', function(assert) {
+ queueRegistryResponse(assert, true);
+ mockGetClientBaseJid();
+ mockHostDaemonFacade.startDaemonResult =
+ remoting.HostController.AsyncResult.CANCELLED;
+ return new Promise(function(resolve, reject) {
+ controller.start(FAKE_HOST_PIN, true, function() {
+ reject('test failed');
+ }, function(/** remoting.Error */ e) {
+ assert.equal(e.getTag(), remoting.Error.Tag.CANCELLED);
+ assert.equal(unregisterHostByIdSpy.callCount, 1);
+ assert.equal(onLocalHostStartedSpy.callCount, 0);
+ resolve(null);
+ });
+ });
+});
+
+// Check what happens when the HostDaemonFacade's startDaemon method
+// calls is onDone method with an async error code.
+QUnit.test('start with startDaemon returning failure code', function(assert) {
+ queueRegistryResponse(assert, true);
+ mockGetClientBaseJid();
+ mockHostDaemonFacade.startDaemonResult =
+ remoting.HostController.AsyncResult.FAILED;
+ return new Promise(function(resolve, reject) {
+ controller.start(FAKE_HOST_PIN, true, function() {
+ reject('test failed');
+ }, function(/** remoting.Error */ e) {
+ assert.equal(e.getTag(), remoting.Error.Tag.UNEXPECTED);
+ assert.equal(unregisterHostByIdSpy.callCount, 1);
+ assert.equal(onLocalHostStartedSpy.callCount, 0);
+ resolve(null);
+ });
+ });
+});
+
+// Check what happens when the entire host registration process
+// succeeds.
+[false, true].forEach(function(/** boolean */ consent) {
+ QUnit.test('start succeeds with consent=' + consent, function(assert) {
+ queueRegistryResponse(assert, true);
+ mockGetClientBaseJid();
+ return new Promise(function(resolve, reject) {
+ controller.start(FAKE_HOST_PIN, consent, function() {
+ assert.equal(getCredentialsFromAuthCodeSpy.callCount, 1);
+ assert.deepEqual(
+ getCredentialsFromAuthCodeSpy.args[0][0],
+ FAKE_AUTH_CODE);
+ assert.equal(getPinHashSpy.callCount, 1);
+ assert.deepEqual(
+ getPinHashSpy.args[0].slice(0, 2),
+ [FAKE_UUID, FAKE_HOST_PIN]);
+
+ assert.equal(unregisterHostByIdSpy.callCount, 0);
+ assert.equal(onLocalHostStartedSpy.callCount, 1);
+ assert.equal(startDaemonSpy.callCount, 1);
+ assert.deepEqual(
+ startDaemonSpy.args[0].slice(0, 2),
+ [{
+ xmpp_login: FAKE_USER_EMAIL,
+ oauth_refresh_token: FAKE_REFRESH_TOKEN,
+ host_owner: FAKE_CLIENT_BASE_JID,
+ host_owner_email: FAKE_USER_EMAIL,
+ host_id: FAKE_UUID,
+ host_name: FAKE_HOST_NAME,
+ host_secret_hash: FAKE_PIN_HASH,
+ private_key: FAKE_PRIVATE_KEY
+ }, consent]);
+ resolve(null);
+ }, reject);
+ });
+ });
+});
+
+// TODO(jrw): Add tests for |stop| method.
+// TODO(jrw): Add tests for |updatePin| method.
+// TODO(jrw): Add tests for |getLocalHostState| method.
+// TODO(jrw): Add tests for |getLocalHostId| method.
+// TODO(jrw): Add tests for |getPairedClients| method.
+// TODO(jrw): Add tests for |deletePairedClient| method.
+// TODO(jrw): Add tests for |clearPairedClients| method.
+// TODO(jrw): Make sure getClientBaseJid_ method is tested.
+
+})();
« no previous file with comments | « remoting/webapp/crd/js/host_controller.js ('k') | remoting/webapp/crd/js/mock_host_daemon_facade.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698