Chromium Code Reviews| Index: chrome/test/data/webui/settings/certificate_manager_page_test.js |
| diff --git a/chrome/test/data/webui/settings/certificate_manager_page_test.js b/chrome/test/data/webui/settings/certificate_manager_page_test.js |
| index b4644ecfa215f1c2f63fc2e34b2c88c7fd1f8b0b..50689e9124c023a24f7ff0e05365f23d2053cbe4 100644 |
| --- a/chrome/test/data/webui/settings/certificate_manager_page_test.js |
| +++ b/chrome/test/data/webui/settings/certificate_manager_page_test.js |
| @@ -16,14 +16,20 @@ cr.define('certificate_manager_page', function() { |
| settings.TestBrowserProxy.call(this, [ |
| 'deleteCertificate', |
| 'editCaCertificateTrust', |
| + 'exportCertificate', |
| + 'exportPersonalCertificate', |
| 'exportPersonalCertificatePasswordSelected', |
| 'getCaCertificateTrust', |
| 'importPersonalCertificatePasswordSelected', |
| 'refreshCertificates', |
| + 'viewCertificate', |
| ]); |
| /** @private {!CaTrustInfo} */ |
| this.caTrustInfo_ = {ssl: true, email: true, objSign: true}; |
| + |
| + /** @private {?CertificatesError} */ |
| + this.certificatesError_ = null; |
| }; |
| TestCertificatesBrowserProxy.prototype = { |
| @@ -47,33 +53,68 @@ cr.define('certificate_manager_page', function() { |
| this.methodCalled('editCaCertificateTrust', { |
| id: id, ssl: ssl, email: email, objSign: objSign, |
| }); |
| - return Promise.resolve(); |
| + return this.fulfillRequest_(); |
| + }, |
| + |
| + /** |
| + * Forces some of the browser proxy methods to start returning errors. |
| + */ |
| + forceCertificatesError: function() { |
| + this.certificatesError_ = /** @type {!CertificatesError} */ ({ |
| + title: 'DummyError', description: 'DummyDescription' |
| + }); |
| + }, |
| + |
| + /** |
| + * @return {!Promise} A promise that is resolved or rejected based on the |
| + * value of |certificatesError_|. |
| + * @private |
| + */ |
| + fulfillRequest_: function() { |
| + return this.certificatesError_ === null ? |
| + Promise.resolve() : Promise.reject(this.certificatesError_); |
| }, |
| /** @override */ |
| deleteCertificate: function(id) { |
| this.methodCalled('deleteCertificate', id); |
| - return Promise.resolve(); |
| + return this.fulfillRequest_(); |
| }, |
| /** @override */ |
| exportPersonalCertificatePasswordSelected: function(password) { |
| this.resolverMap_.get( |
| 'exportPersonalCertificatePasswordSelected').resolve(password); |
| - return Promise.resolve(); |
| + return this.fulfillRequest_(); |
| }, |
| /** @override */ |
| importPersonalCertificatePasswordSelected: function(password) { |
| this.resolverMap_.get( |
| 'importPersonalCertificatePasswordSelected').resolve(password); |
| - return Promise.resolve(); |
| + return this.fulfillRequest_(); |
| }, |
| /** @override */ |
| refreshCertificates: function() { |
| this.methodCalled('refreshCertificates'); |
| }, |
| + |
| + /** @override */ |
| + viewCertificate: function(id) { |
| + this.methodCalled('viewCertificate', id); |
| + }, |
| + |
| + /** @override */ |
| + exportCertificate: function(id) { |
| + this.methodCalled('exportCertificate', id); |
| + }, |
| + |
| + /** @override */ |
| + exportPersonalCertificate: function(id) { |
| + this.methodCalled('exportPersonalCertificate', id); |
| + return Promise.resolve(); |
| + }, |
| }; |
| /** @return {!Certificate} */ |
| @@ -111,6 +152,19 @@ cr.define('certificate_manager_page', function() { |
| MockInteractions.keyEventOn(element, 'input', kSpaceBar); |
| } |
| + /** |
| + * Converts an event occurrence to a promise. |
| + * @param {string} eventType |
| + * @param {!HTMLElement} target |
| + * @return {!Promise} A promise firing once the event occurs. |
| + */ |
| + function waitForEvent(eventType, target) { |
| + return new Promise(function(resolve, reject) { |
| + target.addEventListener(eventType, resolve); |
|
tommycli
2016/03/23 19:28:05
Is it a problem that we never remove the event lis
dpapad
2016/03/24 22:06:11
It is not a problem, for two reasons.
1) "target"
|
| + }); |
| + } |
| + |
|
tommycli
2016/03/23 19:28:05
nit: extra newline
dpapad
2016/03/24 22:06:11
Removed.
|
| + |
| function registerCaTrustEditDialogTests() { |
| /** @type {?SettingsCaTrustEditDialogElement} */ |
| var dialog = null; |
| @@ -138,7 +192,7 @@ cr.define('certificate_manager_page', function() { |
| teardown(function() { dialog.remove(); }); |
| - test('Dialog', function() { |
| + test('EditSuccess', function() { |
| return browserProxy.whenCalled('getCaCertificateTrust').then( |
| function(id) { |
| assertEquals(model.id, id); |
| @@ -154,17 +208,31 @@ cr.define('certificate_manager_page', function() { |
| // Simulate clicking 'OK'. |
| MockInteractions.tap(dialog.$.ok); |
| - return browserProxy.whenCalled('editCaCertificateTrust').then( |
| - function(args) { |
| - assertEquals(model.id, args.id); |
| - // Checking that the values sent to C++ are reflecting the |
| - // changes made by the user (toggling all checkboxes). |
| - assertEquals(caTrustInfo.ssl, !args.ssl); |
| - assertEquals(caTrustInfo.email, !args.email); |
| - assertEquals(caTrustInfo.objSign, !args.objSign); |
| - // Check that the dialog is closed. |
| - assertFalse(dialog.$.dialog.opened); |
| - }); |
| + return browserProxy.whenCalled('editCaCertificateTrust'); |
|
tommycli
2016/03/23 19:28:05
Interesting. I assume you are just linearizing the
dpapad
2016/03/24 22:06:11
Yes, this is a typical case of chaining promises o
|
| + }).then( |
| + function(args) { |
| + assertEquals(model.id, args.id); |
| + // Checking that the values sent to C++ are reflecting the |
| + // changes made by the user (toggling all checkboxes). |
| + assertEquals(caTrustInfo.ssl, !args.ssl); |
| + assertEquals(caTrustInfo.email, !args.email); |
| + assertEquals(caTrustInfo.objSign, !args.objSign); |
| + // Check that the dialog is closed. |
| + assertFalse(dialog.$.dialog.opened); |
| + }); |
| + }); |
| + |
| + test('EditError', function() { |
| + browserProxy.forceCertificatesError(); |
| + var whenErrorEventFired = waitForEvent('certificates-error', dialog); |
| + |
| + return browserProxy.whenCalled('getCaCertificateTrust').then( |
| + function() { |
| + MockInteractions.tap(dialog.$.ok); |
| + return browserProxy.whenCalled('editCaCertificateTrust'); |
| + }).then( |
| + function() { |
| + return whenErrorEventFired; |
| }); |
| }); |
| }); |
| @@ -210,6 +278,20 @@ cr.define('certificate_manager_page', function() { |
| assertFalse(dialog.$.dialog.opened); |
| }); |
| }); |
| + |
| + test('DeleteError', function() { |
| + browserProxy.forceCertificatesError(); |
| + var whenErrorEventFired = waitForEvent('certificates-error', dialog); |
| + |
| + // Simulate clicking 'OK'. |
| + MockInteractions.tap(dialog.$.ok); |
| + return browserProxy.whenCalled('deleteCertificate').then( |
| + function(id) { |
| + assertEquals(model.id, id); |
| + // Ensure that the 'error' event was fired. |
| + return whenErrorEventFired; |
| + }); |
| + }); |
| }); |
| } |
| @@ -223,6 +305,8 @@ cr.define('certificate_manager_page', function() { |
| /** @type {!CertificateSubnode} */ |
| var model = createSampleCertificateSubnode(); |
| + var methodName = 'exportPersonalCertificatePasswordSelected'; |
| + |
| suite('CertificatePasswordEncryptionDialogTests', function() { |
| setup(function() { |
| browserProxy = new TestCertificatesBrowserProxy(); |
| @@ -262,13 +346,31 @@ cr.define('certificate_manager_page', function() { |
| // Simulate clicking 'OK'. |
| MockInteractions.tap(dialog.$.ok); |
| - var methodName = 'exportPersonalCertificatePasswordSelected'; |
| return browserProxy.whenCalled(methodName).then(function(password) { |
| assertEquals(passwordInputElement.value, password); |
| // Check that the dialog is closed. |
| assertFalse(dialog.$.dialog.opened); |
| }); |
| }); |
| + |
| + test('EncryptError', function() { |
| + browserProxy.forceCertificatesError(); |
| + |
| + var passwordInputElements = |
| + Polymer.dom(dialog.$.dialog).querySelectorAll('paper-input'); |
| + var passwordInputElement = passwordInputElements[0]; |
| + passwordInputElement.value = 'foopassword'; |
| + var confirmPasswordInputElement = passwordInputElements[1]; |
| + confirmPasswordInputElement.value = passwordInputElement.value; |
| + triggerInputEvent(passwordInputElement); |
| + |
| + var whenErrorEventFired = waitForEvent('certificates-error', dialog); |
|
tommycli
2016/03/23 19:28:05
It is a bit unfortunate that we have to attach thi
dpapad
2016/03/24 22:06:11
Done. I moved it to the setup() per your 1st sugge
tommycli
2016/03/24 22:34:14
Ah given your point about the scope maybe the orig
|
| + MockInteractions.tap(dialog.$.ok); |
| + |
| + return browserProxy.whenCalled(methodName).then(function() { |
| + return whenErrorEventFired; |
| + }); |
| + }); |
| }); |
| } |
| @@ -279,6 +381,8 @@ cr.define('certificate_manager_page', function() { |
| /** @type {?TestCertificatesBrowserProxy} */ |
| var browserProxy = null; |
| + var methodName = 'importPersonalCertificatePasswordSelected'; |
| + |
| suite('CertificatePasswordDecryptionDialogTests', function() { |
| setup(function() { |
| browserProxy = new TestCertificatesBrowserProxy(); |
| @@ -308,13 +412,138 @@ cr.define('certificate_manager_page', function() { |
| // Simulate clicking 'OK'. |
| MockInteractions.tap(dialog.$.ok); |
| - var methodName = 'importPersonalCertificatePasswordSelected'; |
| return browserProxy.whenCalled(methodName).then(function(password) { |
| assertEquals(passwordInputElement.value, password); |
| // Check that the dialog is closed. |
| assertFalse(dialog.$.dialog.opened); |
| }); |
| }); |
| + |
| + test('DecryptError', function() { |
| + browserProxy.forceCertificatesError(); |
| + // Simulate entering some password. |
| + var passwordInputElement = |
| + Polymer.dom(dialog.$.dialog).querySelector('paper-input'); |
| + passwordInputElement.value = 'foopassword'; |
| + triggerInputEvent(passwordInputElement); |
| + |
| + var whenErrorEventFired = waitForEvent('certificates-error', dialog); |
| + MockInteractions.tap(dialog.$.ok); |
| + return browserProxy.whenCalled(methodName).then(function() { |
| + return whenErrorEventFired; |
| + }); |
| + }); |
| + }); |
| + } |
| + |
| + function registerCertificateSubentryTests() { |
| + var subentry = null; |
| + |
| + /** @type {?TestCertificatesBrowserProxy} */ |
| + var browserProxy = null; |
| + |
| + var waitForActionEvent = function() { |
|
tommycli
2016/03/23 19:28:04
Same comment as above, it would be easier for me t
dpapad
2016/03/24 22:06:11
Added JSDoc for the local function which I think m
|
| + return waitForEvent(settings.CertificateActionEvent, subentry); |
| + }; |
| + |
| + suite('CertificateManagerPageTests', function() { |
| + setup(function() { |
| + browserProxy = new TestCertificatesBrowserProxy(); |
| + settings.CertificatesBrowserProxyImpl.instance_ = browserProxy; |
| + PolymerTest.clearBody(); |
| + subentry = document.createElement('settings-certificate-subentry'); |
| + subentry.model = createSampleCertificateSubnode(); |
| + subentry.certificateType = settings.CertificateType.PERSONAL; |
| + document.body.appendChild(subentry); |
| + |
| + // Bring up the popup menu for the following tests to use. |
| + MockInteractions.tap(subentry.$.dots); |
| + Polymer.dom.flush(); |
| + }); |
| + |
| + teardown(function() { subentry.remove(); }); |
| + |
| + // Test case where 'View' option is tapped. |
| + test('MenuOptions_View', function() { |
| + var viewButton = subentry.shadowRoot.querySelector('#view'); |
| + MockInteractions.tap(viewButton); |
| + return browserProxy.whenCalled('viewCertificate').then(function(id) { |
| + assertEquals(subentry.model.id, id); |
| + }); |
| + }); |
| + |
| + // Test that the 'Edit' option is only shown when appropriate and that |
| + // once tapped the correct event is fired. |
| + test('MenuOptions_Edit', function() { |
| + var editButton = subentry.shadowRoot.querySelector('#edit'); |
| + // Should be disabled for any certificate type other than |
| + // CertificateType.CA |
| + assertTrue(editButton.hidden); |
| + subentry.certificateType = settings.CertificateType.CA; |
| + assertFalse(editButton.hidden); |
| + |
| + var whenActionEventFired = waitForActionEvent(); |
|
tommycli
2016/03/23 19:28:04
Same comment as above, I just found this required
dpapad
2016/03/24 22:06:11
I am sensing that you are not very fond/comfortabl
dpapad
2016/03/24 22:11:17
To be more precise I forgot some stuff in my snipp
tommycli
2016/03/24 22:34:14
Hi Demetrios, Although the above would be easy to
dpapad
2016/03/25 17:36:03
Thanks for explaining the points of confusion Tomm
|
| + MockInteractions.tap(editButton); |
| + return whenActionEventFired.then(function(event) { |
| + var detail = /** @type {!CertificateActionEventDetail} */ ( |
| + event.detail); |
| + assertEquals(settings.CertificateAction.EDIT, detail.action); |
| + assertEquals(subentry.model.id, detail.subnode.id); |
| + assertEquals(subentry.certificateType, detail.certificateType); |
| + }); |
| + }); |
| + |
| + // Test that the 'Delete' option is only shown when appropriate and that |
| + // once tapped the correct event is fired. |
| + test('MenuOptions_Delete', function() { |
| + subentry.set('model.readonly', true); |
| + |
| + var deleteButton = subentry.shadowRoot.querySelector('#delete'); |
| + // Should be disabled when 'model.readonly' is true. |
| + assertTrue(deleteButton.hidden); |
| + subentry.set('model.readonly', false); |
| + assertFalse(deleteButton.hidden); |
| + |
| + var whenActionEventFired = waitForActionEvent(); |
| + MockInteractions.tap(deleteButton); |
| + return whenActionEventFired.then(function(event) { |
| + var detail = /** @type {!CertificateActionEventDetail} */ ( |
| + event.detail); |
| + assertEquals(settings.CertificateAction.DELETE, detail.action); |
| + assertEquals(subentry.model.id, detail.subnode.id); |
| + }); |
| + }); |
| + |
| + // Test case of exporting a certificate that is not PERSONAL. |
| + test('MenuOptions_Export', function() { |
| + subentry.certificateType = settings.CertificateType.SERVER; |
| + var exportButton = subentry.shadowRoot.querySelector('#export'); |
| + MockInteractions.tap(exportButton); |
| + return browserProxy.whenCalled('exportCertificate').then(function(id) { |
| + assertEquals(subentry.model.id, id); |
| + }); |
| + }); |
| + |
| + // Test case of exporting a PERSONAL certificate. |
| + test('MenuOptions_ExportPersonal', function() { |
| + var whenActionEventFired = waitForActionEvent(); |
| + |
| + var exportButton = subentry.shadowRoot.querySelector('#export'); |
| + MockInteractions.tap(exportButton); |
| + return browserProxy.whenCalled('exportPersonalCertificate').then( |
| + function(id) { |
| + assertEquals(subentry.model.id, id); |
| + return whenActionEventFired; |
| + }).then( |
| + function(event) { |
| + var detail = /** @type {!CertificateActionEventDetail} */ ( |
| + event.detail); |
| + assertEquals( |
| + settings.CertificateAction.EXPORT_PERSONAL, |
| + detail.action); |
| + assertEquals(subentry.model.id, detail.subnode.id); |
| + }); |
| + }); |
| }); |
| } |
| @@ -393,6 +622,58 @@ cr.define('certificate_manager_page', function() { |
| assertCertificateListLength(CertificateCategoryIndex.OTHER, 0); |
| }); |
| }); |
| + |
| + /** |
| + * Dispatches a settings.CertificateActionEvent. |
| + * @param {!settings.CertificateAction} action The type of action to |
| + * simulate. |
| + */ |
| + function dispatchCertificateActionEvent(action) { |
| + var eventDetail = /** @type {!CertificateActionEventDetail} */ ({ |
| + action: action, |
| + subnode: createSampleCertificateSubnode(), |
| + certificateType: settings.CertificateType.PERSONAL |
| + }); |
| + page.dispatchEvent(new CustomEvent( |
| + settings.CertificateActionEvent, {detail: eventDetail})); |
| + } |
| + |
| + /** |
| + * Tests that a dialog opens as a response to a |
| + * settings.CertificateActionEvent. |
| + * @param {string} dialogTagName The type of dialog to test. |
| + * @param {!settings.CertificateAction} action The action that is supposed |
| + * to trigger the dialog. |
| + */ |
| + function testDialogOpensOnAction(dialogTagName, action) { |
| + assertFalse(!!page.shadowRoot.querySelector(dialogTagName)); |
| + dispatchCertificateActionEvent(action); |
| + Polymer.dom.flush(); |
| + assertTrue(!!page.shadowRoot.querySelector(dialogTagName)); |
| + } |
| + |
| + test('OpensDialog_DeleteConfirmation', function() { |
| + testDialogOpensOnAction( |
| + 'settings-certificate-delete-confirmation-dialog', |
| + settings.CertificateAction.DELETE); |
| + }); |
| + |
| + test('OpensDialog_PasswordEncryption', function() { |
| + testDialogOpensOnAction( |
| + 'settings-certificate-password-encryption-dialog', |
| + settings.CertificateAction.EXPORT_PERSONAL); |
| + }); |
| + |
| + test('OpensDialog_PasswordDecryption', function() { |
| + testDialogOpensOnAction( |
| + 'settings-certificate-password-decryption-dialog', |
| + settings.CertificateAction.IMPORT_PERSONAL); |
| + }); |
| + |
| + test('OpensDialog_CaTrustEdit', function() { |
| + testDialogOpensOnAction( |
| + 'settings-ca-trust-edit-dialog', settings.CertificateAction.EDIT); |
| + }); |
| }); |
| } |
| @@ -403,6 +684,7 @@ cr.define('certificate_manager_page', function() { |
| registerPasswordEncryptDialogTests(); |
| registerPasswordDecryptDialogTests(); |
| registerPageTests(); |
| + registerCertificateSubentryTests(); |
| }, |
| }; |
| }); |