UI: Display minus icon for empty MaskedInput value. Show MaskedInput for KV secrets without values (#22039)

* changed MaskedInput to show a minus icon when there is no value. changed SecretFormShow to show this MaskedInput with minus icon instead of showing just a minus icon

* fixed copy button for blank value in MaskedInput; added changelog

* reword changelog to be more concise

* added test to check if minus icon shows for MaskedInput when value is empty string

* edited a test to make sytnax more concise

* changed MaskedInput to show 'danger' message when copying empty value

* added 2 tests to check for flash messages

* changed naming of a MaskedInput test to be more descriptive
This commit is contained in:
malinac02
2023-07-31 12:29:43 -07:00
committed by GitHub
parent 8253e59752
commit 7e6bb1fb7c
5 changed files with 78 additions and 13 deletions

3
changelog/22039.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:improvement
ui: Display minus icon for empty MaskedInput value. Show MaskedInput for KV secrets without values
```

View File

@@ -65,17 +65,13 @@
{{#if @modelForData.secretKeyAndValue}}
{{#each @modelForData.secretKeyAndValue as |secret|}}
<InfoTableRow @label={{secret.key}} @value={{secret.value}} @alwaysRender={{true}}>
{{#if secret.value}}
<MaskedInput
@name={{secret.key}}
@value={{secret.value}}
@displayOnly={{true}}
@allowCopy={{true}}
@allowDownload={{@isV2}}
/>
{{else}}
<Icon @name="minus" />
{{/if}}
<MaskedInput
@name={{secret.key}}
@value={{secret.value}}
@displayOnly={{true}}
@allowCopy={{true}}
@allowDownload={{@isV2}}
/>
</InfoTableRow>
{{/each}}
{{else}}

View File

@@ -6,7 +6,12 @@
>
{{#if @displayOnly}}
{{#if this.showValue}}
<pre class="masked-value display-only is-word-break">{{@value}}</pre>
{{! Show minus icon if there is no value }}
{{#if (eq @value "")}}
<Icon class="masked-value" @name="minus" />
{{else}}
<pre class="masked-value display-only is-word-break">{{@value}}</pre>
{{/if}}
{{else}}
<pre class="masked-value display-only masked-font">***********</pre>
{{/if}}
@@ -28,6 +33,7 @@
<CopyButton
@clipboardText={{@value}}
@success={{action (set-flash-message "Data copied!")}}
@error={{action (set-flash-message "Error copying data" "danger")}}
class="copy-button button {{if @displayOnly 'is-compact'}}"
data-test-copy-button
>
@@ -50,7 +56,7 @@
type="button"
aria-label={{if this.showValue "mask value" "show value"}}
title={{if this.showValue "mask value" "show value"}}
class="{{if (eq @value '') 'has-text-grey'}} masked-input-toggle button"
class="masked-input-toggle button"
data-test-button="toggle-masked"
>
<Icon @name={{if this.showValue "eye" "eye-off"}} />

View File

@@ -16,6 +16,13 @@ const component = create(maskedInput);
module('Integration | Component | masked input', function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function () {
this.flashMessages = this.owner.lookup('service:flash-messages');
this.flashMessages.registerTypes(['success', 'danger']);
this.flashSuccessSpy = sinon.spy(this.flashMessages, 'success');
this.flashDangerSpy = sinon.spy(this.flashMessages, 'danger');
});
test('it renders', async function (assert) {
await render(hbs`<MaskedInput />`);
assert.dom('[data-test-masked-input]').exists('shows masked input');
@@ -96,4 +103,56 @@ module('Integration | Component | masked input', function (hooks) {
const unMaskedValue = document.querySelector('.masked-value').value;
assert.strictEqual(unMaskedValue, this.value);
});
test('it renders a minus icon when an empty string is provided as a value', async function (assert) {
await render(hbs`
<MaskedInput
@name="key"
@value=""
@displayOnly={{true}}
@allowCopy={{true}}
@allowDownload={{true}}
/>
`);
assert.dom('[data-test-masked-input]').exists('shows masked input');
assert.ok(component.copyButtonIsPresent);
assert.ok(component.downloadButtonIsPresent);
assert.dom('[data-test-button="toggle-masked"]').exists('shows toggle mask button');
await component.toggleMasked();
assert.dom('.masked-value').doesNotHaveClass('masked-font', 'it unmasks when show button is clicked');
assert
.dom('[data-test-icon="minus"]')
.exists('shows minus icon when unmasked because value is empty string');
});
test('it shows "success" flash message when the value is successfully copied', async function (assert) {
await render(hbs`
<MaskedInput
@name="key"
@value="value"
@displayOnly={{true}}
@allowCopy={{true}}
/>
`);
assert.dom('[data-test-masked-input]').exists('shows masked input');
assert.ok(component.copyButtonIsPresent);
await component.copyValue();
assert.ok(this.flashSuccessSpy.calledWith('Data copied!'), 'Renders correct flash message');
});
test('it shows "danger" flash message when the value fails to be copied (no value)', async function (assert) {
await render(hbs`
<MaskedInput
@name="key"
@value=""
@displayOnly={{true}}
@allowCopy={{true}}
/>
`);
assert.dom('[data-test-masked-input]').exists('shows masked input');
assert.ok(component.copyButtonIsPresent);
await component.copyValue();
assert.ok(this.flashDangerSpy.calledWith('Error copying data'), 'Renders correct flash message');
});
});

View File

@@ -10,4 +10,5 @@ export default {
copyButtonIsPresent: isPresent('[data-test-copy-button]'),
downloadButtonIsPresent: isPresent('[data-test-download-button]'),
toggleMasked: clickable('[data-test-button="toggle-masked"]'),
copyValue: clickable('[data-test-copy-button]'),
};