| /** |
| * @license |
| * Copyright 2017 Google LLC |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| import * as sinon from 'sinon'; |
| import '../../../test/common-test-setup'; |
| import './gr-gpg-editor'; |
| import { |
| mockPromise, |
| queryAll, |
| queryAndAssert, |
| stubRestApi, |
| } from '../../../test/test-utils'; |
| import {GrGpgEditor} from './gr-gpg-editor'; |
| import { |
| GpgKeyFingerprint, |
| GpgKeyInfo, |
| GpgKeyInfoStatus, |
| OpenPgpUserIds, |
| } from '../../../api/rest-api'; |
| import {GrButton} from '../../shared/gr-button/gr-button'; |
| import {fixture, html, assert} from '@open-wc/testing'; |
| |
| suite('gr-gpg-editor tests', () => { |
| let element: GrGpgEditor; |
| let keys: Record<string, GpgKeyInfo>; |
| |
| setup(async () => { |
| const fingerprint1 = |
| '0192 723D 42D1 0C5B 32A6 E1E0 9350 9E4B AFC8 A49B' as GpgKeyFingerprint; |
| const fingerprint2 = |
| '0196 723D 42D1 0C5B 32A6 E1E0 9350 9E4B AFC8 A49B' as GpgKeyFingerprint; |
| keys = { |
| AFC8A49B: { |
| fingerprint: fingerprint1, |
| user_ids: ['John Doe john.doe@example.com'] as OpenPgpUserIds[], |
| key: |
| '-----BEGIN PGP PUBLIC KEY BLOCK-----' + |
| '\nVersion: BCPG v1.52\n\t<key 1>', |
| status: 'TRUSTED' as GpgKeyInfoStatus, |
| problems: [], |
| }, |
| AED9B59C: { |
| fingerprint: fingerprint2, |
| user_ids: ['Gerrit gerrit@example.com'] as OpenPgpUserIds[], |
| key: |
| '-----BEGIN PGP PUBLIC KEY BLOCK-----' + |
| '\nVersion: BCPG v1.52\n\t<key 2>', |
| status: 'TRUSTED' as GpgKeyInfoStatus, |
| problems: [], |
| }, |
| }; |
| |
| stubRestApi('getAccountGPGKeys').returns(Promise.resolve(keys)); |
| |
| element = await fixture(html`<gr-gpg-editor></gr-gpg-editor>`); |
| |
| await element.loadData(); |
| await element.updateComplete; |
| }); |
| |
| test('renders', () => { |
| assert.shadowDom.equal( |
| element, |
| /* HTML */ `<div class="gr-form-styles"> |
| <fieldset id="existing"> |
| <table> |
| <thead> |
| <tr> |
| <th class="idColumn">ID</th> |
| <th class="fingerPrintColumn">Fingerprint</th> |
| <th class="userIdHeader">User IDs</th> |
| <th class="keyHeader">Public Key</th> |
| <th></th> |
| <th></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="idColumn">AFC8A49B</td> |
| <td class="fingerPrintColumn"> |
| 0192 723D 42D1 0C5B 32A6 E1E0 9350 9E4B AFC8 A49B |
| </td> |
| <td class="userIdHeader">John Doe john.doe@example.com</td> |
| <td class="keyHeader"> |
| <gr-button |
| aria-disabled="false" |
| link="" |
| role="button" |
| tabindex="0" |
| > |
| Click to View |
| </gr-button> |
| </td> |
| <td> |
| <gr-copy-clipboard |
| buttontitle="Copy GPG public key to clipboard" |
| hastooltip="" |
| hideinput="" |
| > |
| </gr-copy-clipboard> |
| </td> |
| <td> |
| <gr-button aria-disabled="false" role="button" tabindex="0"> |
| Delete |
| </gr-button> |
| </td> |
| </tr> |
| <tr> |
| <td class="idColumn">AED9B59C</td> |
| <td class="fingerPrintColumn"> |
| 0196 723D 42D1 0C5B 32A6 E1E0 9350 9E4B AFC8 A49B |
| </td> |
| <td class="userIdHeader">Gerrit gerrit@example.com</td> |
| <td class="keyHeader"> |
| <gr-button |
| aria-disabled="false" |
| link="" |
| role="button" |
| tabindex="0" |
| > |
| Click to View |
| </gr-button> |
| </td> |
| <td> |
| <gr-copy-clipboard |
| buttontitle="Copy GPG public key to clipboard" |
| hastooltip="" |
| hideinput="" |
| > |
| </gr-copy-clipboard> |
| </td> |
| <td> |
| <gr-button aria-disabled="false" role="button" tabindex="0"> |
| Delete |
| </gr-button> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| <dialog id="viewKeyModal" tabindex="-1"> |
| <fieldset> |
| <section> |
| <span class="title"> Status </span> <span class="value"> </span> |
| </section> |
| <section> |
| <span class="title"> Key </span> <span class="value"> </span> |
| </section> |
| </fieldset> |
| <gr-button |
| aria-disabled="false" |
| class="closeButton" |
| role="button" |
| tabindex="0" |
| > |
| Close |
| </gr-button> |
| </dialog> |
| <gr-button |
| aria-disabled="true" |
| disabled="" |
| role="button" |
| tabindex="-1" |
| > |
| Save changes |
| </gr-button> |
| </fieldset> |
| <fieldset> |
| <section> |
| <span class="title"> New GPG key </span> |
| <span class="value"> |
| <iron-autogrow-textarea |
| aria-disabled="false" |
| autocomplete="on" |
| id="newKey" |
| placeholder="New GPG Key" |
| > |
| </iron-autogrow-textarea> |
| </span> |
| </section> |
| <gr-button |
| aria-disabled="true" |
| disabled="" |
| id="addButton" |
| role="button" |
| tabindex="-1" |
| > |
| Add new GPG key |
| </gr-button> |
| </fieldset> |
| </div> ` |
| ); |
| }); |
| |
| test('renders', () => { |
| const rows = queryAll(element, 'tbody tr'); |
| |
| assert.equal(rows.length, 2); |
| |
| let cells = rows[0].querySelectorAll('td'); |
| assert.equal(cells[0].textContent, 'AFC8A49B'); |
| |
| cells = rows[1].querySelectorAll('td'); |
| assert.equal(cells[0].textContent, 'AED9B59C'); |
| }); |
| |
| test('remove key', async () => { |
| const lastKey = keys[Object.keys(keys)[1]]; |
| |
| const saveStub = stubRestApi('deleteAccountGPGKey').callsFake(() => |
| Promise.resolve(new Response()) |
| ); |
| |
| assert.equal(element.keysToRemove.length, 0); |
| assert.isFalse(element.hasUnsavedChanges); |
| |
| // Get the delete button for the last row. |
| const button = queryAndAssert<GrButton>( |
| element, |
| 'tbody tr:last-of-type td:nth-child(6) gr-button' |
| ); |
| |
| button.click(); |
| |
| assert.equal(element.keys.length, 1); |
| assert.equal(element.keysToRemove.length, 1); |
| assert.equal(element.keysToRemove[0], lastKey); |
| assert.isTrue(element.hasUnsavedChanges); |
| assert.isFalse(saveStub.called); |
| |
| await element.save(); |
| assert.isTrue(saveStub.called); |
| assert.equal(saveStub.lastCall.args[0], Object.keys(keys)[1]); |
| assert.equal(element.keysToRemove.length, 0); |
| assert.isFalse(element.hasUnsavedChanges); |
| }); |
| |
| test('show key', () => { |
| const openSpy = sinon.spy(element.viewKeyModal!, 'showModal'); |
| |
| // Get the show button for the last row. |
| const button = queryAndAssert<GrButton>( |
| element, |
| 'tbody tr:last-of-type td:nth-child(4) gr-button' |
| ); |
| |
| button.click(); |
| assert.equal(element.keyToView, keys[Object.keys(keys)[1]]); |
| assert.isTrue(openSpy.called); |
| }); |
| |
| test('add key', async () => { |
| const newKeyString = |
| '-----BEGIN PGP PUBLIC KEY BLOCK-----' + ' Version: BCPG v1.52 \t<key 3>'; |
| const newKeyObject = { |
| ADE8A59B: { |
| fingerprint: |
| '0194 723D 42D1 0C5B 32A6 E1E0 9350 9E4B AFC8 A49B' as GpgKeyFingerprint, |
| user_ids: ['John john@example.com'] as OpenPgpUserIds[], |
| key: newKeyString, |
| status: 'TRUSTED' as GpgKeyInfoStatus, |
| problems: [], |
| }, |
| }; |
| |
| const addStub = stubRestApi('addAccountGPGKey').callsFake(() => |
| Promise.resolve(newKeyObject) |
| ); |
| |
| element.newKey = newKeyString; |
| await element.updateComplete; |
| |
| assert.isFalse(element.addButton!.disabled); |
| assert.isFalse(element.newKeyTextarea!.disabled); |
| |
| const promise = mockPromise(); |
| element.handleAddKey().then(() => { |
| assert.isTrue(element.addButton!.disabled); |
| assert.isFalse(element.newKeyTextarea!.disabled); |
| assert.equal(element.keys.length, 2); |
| promise.resolve(); |
| }); |
| |
| assert.isTrue(element.addButton!.disabled); |
| assert.isTrue(element.newKeyTextarea!.disabled); |
| |
| assert.isTrue(addStub.called); |
| assert.deepEqual(addStub.lastCall.args[0], {add: [newKeyString]}); |
| await promise; |
| }); |
| |
| test('add invalid key', async () => { |
| const newKeyString = 'not even close to valid'; |
| |
| const addStub = stubRestApi('addAccountGPGKey').callsFake(() => |
| Promise.reject(new Error('error')) |
| ); |
| |
| element.newKey = newKeyString; |
| await element.updateComplete; |
| |
| assert.isFalse(element.addButton!.disabled); |
| assert.isFalse(element.newKeyTextarea!.disabled); |
| |
| const promise = mockPromise(); |
| element.handleAddKey().then(() => { |
| assert.isFalse(element.addButton!.disabled); |
| assert.isFalse(element.newKeyTextarea!.disabled); |
| assert.equal(element.keys.length, 2); |
| promise.resolve(); |
| }); |
| |
| assert.isTrue(element.addButton!.disabled); |
| assert.isTrue(element.newKeyTextarea!.disabled); |
| |
| assert.isTrue(addStub.called); |
| assert.deepEqual(addStub.lastCall.args[0], {add: [newKeyString]}); |
| await promise; |
| }); |
| }); |