mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 18:17:55 +00:00
Address a11y issues in browser-based console UI (#26872)
This commit is contained in:
3
changelog/26872.txt
Normal file
3
changelog/26872.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
```release-note:bug
|
||||||
|
ui: Resolved accessibility issues with Web REPL. Associated label and help text with input, added a conditional to show the console/ui-panel only when toggled open, added keyboard focus trap.
|
||||||
|
```
|
||||||
@@ -17,16 +17,17 @@ export default Component.extend({
|
|||||||
actions: {
|
actions: {
|
||||||
handleKeyUp(event) {
|
handleKeyUp(event) {
|
||||||
const keyCode = event.keyCode;
|
const keyCode = event.keyCode;
|
||||||
|
const val = event.target.value;
|
||||||
switch (keyCode) {
|
switch (keyCode) {
|
||||||
case keys.ENTER:
|
case keys.ENTER:
|
||||||
this.onExecuteCommand(event.target.value);
|
this.onExecuteCommand(val);
|
||||||
break;
|
break;
|
||||||
case keys.UP:
|
case keys.UP:
|
||||||
case keys.DOWN:
|
case keys.DOWN:
|
||||||
this.onShiftCommand(keyCode);
|
this.onShiftCommand(keyCode);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.onValueUpdate(event.target.value);
|
this.onValueUpdate(val);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fullscreen() {
|
fullscreen() {
|
||||||
|
|||||||
@@ -49,7 +49,14 @@
|
|||||||
<LinkStatus @status={{this.currentCluster.cluster.hcpLinkStatus}} />
|
<LinkStatus @status={{this.currentCluster.cluster.hcpLinkStatus}} />
|
||||||
{{yield}}
|
{{yield}}
|
||||||
<div data-test-console-panel class={{if this.console.isOpen "panel-open"}}>
|
<div data-test-console-panel class={{if this.console.isOpen "panel-open"}}>
|
||||||
<Console::UiPanel @isFullscreen={{this.consoleFullscreen}} />
|
{{#if this.console.isOpen}}
|
||||||
|
<Console::UiPanel
|
||||||
|
@isFullscreen={{this.consoleFullscreen}}
|
||||||
|
{{focus-trap
|
||||||
|
focusTrapOptions=(hash initialFocus="#console-input" clickOutsideDeactivates=true onDeactivate=this.closeConsole)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</Frame.Main>
|
</Frame.Main>
|
||||||
</Hds::AppFrame>
|
</Hds::AppFrame>
|
||||||
@@ -14,7 +14,9 @@ $console-close-height: 35px;
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
transition: min-height $speed $easing, transform $speed ease-in;
|
transition:
|
||||||
|
min-height $speed $easing,
|
||||||
|
transform $speed ease-in;
|
||||||
will-change: transform, min-height;
|
will-change: transform, min-height;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
z-index: 199;
|
z-index: 199;
|
||||||
@@ -118,11 +120,11 @@ $console-close-height: 35px;
|
|||||||
|
|
||||||
.panel-open .console-ui-panel {
|
.panel-open .console-ui-panel {
|
||||||
box-shadow: $box-shadow-highest;
|
box-shadow: $box-shadow-highest;
|
||||||
min-height: 400px;
|
min-height: 425px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main--console-open {
|
.main--console-open {
|
||||||
padding-bottom: 400px;
|
padding-bottom: 425px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-open .console-ui-panel.fullscreen {
|
.panel-open .console-ui-panel.fullscreen {
|
||||||
|
|||||||
@@ -10,19 +10,20 @@
|
|||||||
<Chevron />
|
<Chevron />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<input
|
<input
|
||||||
aria-label="command input"
|
aria-label="web R.E.P.L."
|
||||||
|
aria-describedby="namespace-reminder"
|
||||||
onkeyup={{action "handleKeyUp"}}
|
onkeyup={{action "handleKeyUp"}}
|
||||||
value={{this.value}}
|
value={{this.value}}
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
|
id="console-input"
|
||||||
/>
|
/>
|
||||||
<Hds::Button
|
<Hds::Button
|
||||||
class="hds-side-nav__icon-button"
|
class="hds-side-nav__icon-button"
|
||||||
{{on "click" (action "fullscreen")}}
|
{{on "click" (action "fullscreen")}}
|
||||||
{{hds-tooltip (if this.isFullscreen "minimize" "maximize")}}
|
data-test-dismiss-console-button
|
||||||
data-test-tool-tip-trigger
|
|
||||||
@icon={{if this.isFullscreen "minimize" "maximize"}}
|
@icon={{if this.isFullscreen "minimize" "maximize"}}
|
||||||
@text={{if this.isFullscreen "Minimize" "Maximize"}}
|
@text={{if this.isFullscreen "Minimize window" "Maximize window"}}
|
||||||
@isIconOnly={{true}}
|
@isIconOnly={{true}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,17 +3,19 @@
|
|||||||
SPDX-License-Identifier: BUSL-1.1
|
SPDX-License-Identifier: BUSL-1.1
|
||||||
~}}
|
~}}
|
||||||
|
|
||||||
<div class="console-close-button">
|
|
||||||
<Hds::Button
|
|
||||||
class="hds-side-nav__icon-button"
|
|
||||||
{{on "click" (action "closeConsole")}}
|
|
||||||
data-test-console-panel-close
|
|
||||||
@text="Close console"
|
|
||||||
@icon="x"
|
|
||||||
@isIconOnly={{true}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="console-ui-panel-content">
|
<div class="console-ui-panel-content">
|
||||||
|
<div class="content has-bottom-margin-s">
|
||||||
|
<div class="console-close-button">
|
||||||
|
<Hds::Button
|
||||||
|
class="hds-side-nav__icon-button"
|
||||||
|
{{on "click" (action "closeConsole")}}
|
||||||
|
data-test-console-panel-close
|
||||||
|
@text="Close console"
|
||||||
|
@icon="x"
|
||||||
|
@isIconOnly={{true}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="content has-bottom-margin-l">
|
<div class="content has-bottom-margin-l">
|
||||||
<p class="console-ui-panel-intro is-font-mono has-bottom-margin-s">
|
<p class="console-ui-panel-intro is-font-mono has-bottom-margin-s">
|
||||||
The Vault Web REPL provides an easy way to execute common Vault CLI commands, such as write, read, delete, and list. It
|
The Vault Web REPL provides an easy way to execute common Vault CLI commands, such as write, read, delete, and list. It
|
||||||
@@ -22,14 +24,18 @@
|
|||||||
<Hds::Link::Inline @href={{doc-link "/vault/docs/command/web"}}>HashiCorp Developer site</Hds::Link::Inline>.
|
<Hds::Link::Inline @href={{doc-link "/vault/docs/command/web"}}>HashiCorp Developer site</Hds::Link::Inline>.
|
||||||
</p>
|
</p>
|
||||||
<p class="console-ui-panel-intro is-font-mono has-bottom-margin-s">Examples:</p>
|
<p class="console-ui-panel-intro is-font-mono has-bottom-margin-s">Examples:</p>
|
||||||
<p class="console-ui-panel-intro is-font-mono">→ Write secrets to kv v1: write <mount>/my-secret foo=bar</p>
|
<p class="console-ui-panel-intro is-font-mono">
|
||||||
<p class="console-ui-panel-intro is-font-mono">→ List kv v1 secret keys: list <mount>/</p>
|
<span aria-hidden="true">→ </span>Write secrets to kv v1: write <mount>/my-secret foo=bar</p>
|
||||||
<p class="console-ui-panel-intro is-font-mono">→ Read a kv v1 secret: read <mount>/my-secret</p>
|
<p class="console-ui-panel-intro is-font-mono">
|
||||||
<p class="console-ui-panel-intro is-font-mono">→ Mount a kv v2 secret engine: write sys/mounts/<mount> type=kv
|
<span aria-hidden="true">→ </span>List kv v1 secret keys: list <mount>/</p>
|
||||||
options=version=2</p>
|
<p class="console-ui-panel-intro is-font-mono">
|
||||||
<p class="console-ui-panel-intro is-font-mono">→ Read a kv v2 secret: kv-get <mount>/secret-path</p>
|
<span aria-hidden="true">→ </span>Read a kv v1 secret: read <mount>/my-secret</p>
|
||||||
<p class="console-ui-panel-intro is-font-mono">→ Read a kv v2 secret's metadata: kv-get <mount>/secret-path
|
<p class="console-ui-panel-intro is-font-mono">
|
||||||
-metadata</p>
|
<span aria-hidden="true">→ </span>Mount a kv v2 secret engine: write sys/mounts/<mount> type=kv options=version=2</p>
|
||||||
|
<p class="console-ui-panel-intro is-font-mono">
|
||||||
|
<span aria-hidden="true">→ </span>Read a kv v2 secret: kv-get <mount>/secret-path</p>
|
||||||
|
<p class="console-ui-panel-intro is-font-mono">
|
||||||
|
<span aria-hidden="true">→ </span>Read a kv v2 secret's metadata: kv-get <mount>/secret-path-metadata</p>
|
||||||
</div>
|
</div>
|
||||||
<Console::OutputLog @outputLog={{this.cliLog}} />
|
<Console::OutputLog @outputLog={{this.cliLog}} />
|
||||||
<Console::CommandInput
|
<Console::CommandInput
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
{{#if this.showMessage}}
|
{{#if this.showMessage}}
|
||||||
{{#if (has-block)}}
|
{{#if (has-block)}}
|
||||||
<p class="namespace-reminder">
|
<p class="namespace-reminder" id="namespace-reminder">
|
||||||
{{yield (hash namespace=this.namespace)}}
|
{{yield (hash namespace=this.namespace)}}
|
||||||
</p>
|
</p>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p class="namespace-reminder">
|
<p class="namespace-reminder" id="namespace-reminder">
|
||||||
This
|
This
|
||||||
{{@noun}}
|
{{@noun}}
|
||||||
will be
|
will be
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ module('Acceptance | console', function (hooks) {
|
|||||||
assert.expect(6);
|
assert.expect(6);
|
||||||
await enginesPage.visit();
|
await enginesPage.visit();
|
||||||
await settled();
|
await settled();
|
||||||
await consoleComponent.toggle();
|
|
||||||
await settled();
|
|
||||||
const ids = [uuidv4(), uuidv4(), uuidv4()];
|
const ids = [uuidv4(), uuidv4(), uuidv4()];
|
||||||
for (const id of ids) {
|
for (const id of ids) {
|
||||||
const inputString = `write sys/mounts/console-route-${id} type=kv`;
|
const inputString = `write sys/mounts/console-route-${id} type=kv`;
|
||||||
@@ -59,7 +57,7 @@ module('Acceptance | console', function (hooks) {
|
|||||||
test('fullscreen command expands the cli panel', async function (assert) {
|
test('fullscreen command expands the cli panel', async function (assert) {
|
||||||
await consoleComponent.toggle();
|
await consoleComponent.toggle();
|
||||||
await settled();
|
await settled();
|
||||||
await consoleComponent.runCommands('fullscreen');
|
await consoleComponent.runCommands('fullscreen', false);
|
||||||
await settled();
|
await settled();
|
||||||
const consoleEle = document.querySelector('[data-test-component="console/ui-panel"]');
|
const consoleEle = document.querySelector('[data-test-component="console/ui-panel"]');
|
||||||
// wait for the CSS transition to finish
|
// wait for the CSS transition to finish
|
||||||
@@ -74,7 +72,7 @@ module('Acceptance | console', function (hooks) {
|
|||||||
test('array output is correctly formatted', async function (assert) {
|
test('array output is correctly formatted', async function (assert) {
|
||||||
await consoleComponent.toggle();
|
await consoleComponent.toggle();
|
||||||
await settled();
|
await settled();
|
||||||
await consoleComponent.runCommands('read -field=policies /auth/token/lookup-self');
|
await consoleComponent.runCommands('read -field=policies /auth/token/lookup-self', false);
|
||||||
await settled();
|
await settled();
|
||||||
const consoleOut = document.querySelector('.console-ui-output>pre');
|
const consoleOut = document.querySelector('.console-ui-output>pre');
|
||||||
// wait for the CSS transition to finish
|
// wait for the CSS transition to finish
|
||||||
@@ -86,7 +84,7 @@ module('Acceptance | console', function (hooks) {
|
|||||||
test('number output is correctly formatted', async function (assert) {
|
test('number output is correctly formatted', async function (assert) {
|
||||||
await consoleComponent.toggle();
|
await consoleComponent.toggle();
|
||||||
await settled();
|
await settled();
|
||||||
await consoleComponent.runCommands('read -field=creation_time /auth/token/lookup-self');
|
await consoleComponent.runCommands('read -field=creation_time /auth/token/lookup-self', false);
|
||||||
await settled();
|
await settled();
|
||||||
const consoleOut = document.querySelector('.console-ui-output>pre');
|
const consoleOut = document.querySelector('.console-ui-output>pre');
|
||||||
// wait for the CSS transition to finish
|
// wait for the CSS transition to finish
|
||||||
@@ -97,7 +95,7 @@ module('Acceptance | console', function (hooks) {
|
|||||||
test('boolean output is correctly formatted', async function (assert) {
|
test('boolean output is correctly formatted', async function (assert) {
|
||||||
await consoleComponent.toggle();
|
await consoleComponent.toggle();
|
||||||
await settled();
|
await settled();
|
||||||
await consoleComponent.runCommands('read -field=orphan /auth/token/lookup-self');
|
await consoleComponent.runCommands('read -field=orphan /auth/token/lookup-self', false);
|
||||||
await settled();
|
await settled();
|
||||||
const consoleOut = document.querySelector('.console-ui-output>pre');
|
const consoleOut = document.querySelector('.console-ui-output>pre');
|
||||||
// have to wrap in a later so that we can wait for the CSS transition to finish
|
// have to wrap in a later so that we can wait for the CSS transition to finish
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ module('Acceptance | pki workflow', function (hooks) {
|
|||||||
allow_subdomains=true \
|
allow_subdomains=true \
|
||||||
max_ttl="720h"`,
|
max_ttl="720h"`,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await runCmd([`write ${this.mountPath}/root/generate/internal common_name="Hashicorp Test"`]);
|
await runCmd([`write ${this.mountPath}/root/generate/internal common_name="Hashicorp Test"`]);
|
||||||
const pki_admin_policy = adminPolicy(this.mountPath, 'roles');
|
const pki_admin_policy = adminPolicy(this.mountPath, 'roles');
|
||||||
const pki_reader_policy = readerPolicy(this.mountPath, 'roles');
|
const pki_reader_policy = readerPolicy(this.mountPath, 'roles');
|
||||||
|
|||||||
@@ -25,7 +25,12 @@ const visit = async (url) => {
|
|||||||
const consoleComponent = create(consoleClass);
|
const consoleComponent = create(consoleClass);
|
||||||
|
|
||||||
const wrappedAuth = async () => {
|
const wrappedAuth = async () => {
|
||||||
await consoleComponent.runCommands(`write -field=token auth/token/create policies=default -wrap-ttl=5m`);
|
await consoleComponent.toggle();
|
||||||
|
await settled();
|
||||||
|
await consoleComponent.runCommands(
|
||||||
|
`write -field=token auth/token/create policies=default -wrap-ttl=5m`,
|
||||||
|
false
|
||||||
|
);
|
||||||
await settled();
|
await settled();
|
||||||
// because of flaky test, trying to capture the token using a dom selector instead of the page object
|
// because of flaky test, trying to capture the token using a dom selector instead of the page object
|
||||||
const token = document.querySelector('[data-test-component="console/log-text"] pre').textContent;
|
const token = document.querySelector('[data-test-component="console/log-text"] pre').textContent;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { module, test } from 'qunit';
|
|||||||
import { setupApplicationTest } from 'ember-qunit';
|
import { setupApplicationTest } from 'ember-qunit';
|
||||||
import { setupMirage } from 'ember-cli-mirage/test-support';
|
import { setupMirage } from 'ember-cli-mirage/test-support';
|
||||||
import { create } from 'ember-cli-page-object';
|
import { create } from 'ember-cli-page-object';
|
||||||
import { fillIn } from '@ember/test-helpers';
|
import { fillIn, settled } from '@ember/test-helpers';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
import enablePage from 'vault/tests/pages/settings/auth/enable';
|
import enablePage from 'vault/tests/pages/settings/auth/enable';
|
||||||
@@ -59,6 +59,8 @@ module('Acceptance | settings/auth/configure/section', function (hooks) {
|
|||||||
for (const type of ['aws', 'azure', 'gcp', 'github', 'kubernetes']) {
|
for (const type of ['aws', 'azure', 'gcp', 'github', 'kubernetes']) {
|
||||||
test(`it shows tabs for auth method: ${type}`, async function (assert) {
|
test(`it shows tabs for auth method: ${type}`, async function (assert) {
|
||||||
const path = `${type}-showtab-${this.uid}`;
|
const path = `${type}-showtab-${this.uid}`;
|
||||||
|
await cli.toggle();
|
||||||
|
await settled();
|
||||||
await cli.consoleInput(`write sys/auth/${path} type=${type}`);
|
await cli.consoleInput(`write sys/auth/${path} type=${type}`);
|
||||||
await cli.enter();
|
await cli.enter();
|
||||||
await indexPage.visit({ path });
|
await indexPage.visit({ path });
|
||||||
|
|||||||
@@ -153,12 +153,16 @@ module('Acceptance | settings/mount-secret-backend', function (hooks) {
|
|||||||
capabilities = ["read"]
|
capabilities = ["read"]
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
await consoleComponent.runCommands([
|
await consoleComponent.toggle();
|
||||||
// delete any previous mount with same name
|
await consoleComponent.runCommands(
|
||||||
`delete sys/mounts/${enginePath}`,
|
[
|
||||||
`write sys/policies/acl/kv-v2-degrade policy=${btoa(V2_POLICY)}`,
|
// delete any previous mount with same name
|
||||||
'write -field=client_token auth/token/create policies=kv-v2-degrade',
|
`delete sys/mounts/${enginePath}`,
|
||||||
]);
|
`write sys/policies/acl/kv-v2-degrade policy=${btoa(V2_POLICY)}`,
|
||||||
|
'write -field=client_token auth/token/create policies=kv-v2-degrade',
|
||||||
|
],
|
||||||
|
false
|
||||||
|
);
|
||||||
await settled();
|
await settled();
|
||||||
const userToken = consoleComponent.lastLogOutput;
|
const userToken = consoleComponent.lastLogOutput;
|
||||||
await logout.visit();
|
await logout.visit();
|
||||||
|
|||||||
@@ -14,7 +14,12 @@ import consoleClass from 'vault/tests/pages/components/console/ui-panel';
|
|||||||
const consoleComponent = create(consoleClass);
|
const consoleComponent = create(consoleClass);
|
||||||
|
|
||||||
const wrappedAuth = async () => {
|
const wrappedAuth = async () => {
|
||||||
await consoleComponent.runCommands(`write -field=token auth/token/create policies=default -wrap-ttl=3m`);
|
await consoleComponent.toggle();
|
||||||
|
await settled();
|
||||||
|
await consoleComponent.runCommands(
|
||||||
|
`write -field=token auth/token/create policies=default -wrap-ttl=3m`,
|
||||||
|
false
|
||||||
|
);
|
||||||
await settled();
|
await settled();
|
||||||
return consoleComponent.lastLogOutput;
|
return consoleComponent.lastLogOutput;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import consoleClass from 'vault/tests/pages/components/console/ui-panel';
|
|
||||||
import { create } from 'ember-cli-page-object';
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) HashiCorp, Inc.
|
* Copyright (c) HashiCorp, Inc.
|
||||||
* SPDX-License-Identifier: BUSL-1.1
|
* SPDX-License-Identifier: BUSL-1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import consoleClass from 'vault/tests/pages/components/console/ui-panel';
|
||||||
|
import { create } from 'ember-cli-page-object';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper functions to run common commands in the consoleComponent during tests.
|
* Helper functions to run common commands in the consoleComponent during tests.
|
||||||
* Please note that a user must be logged in during the test context for the commands to run.
|
* Please note that a user must be logged in during the test context for the commands to run.
|
||||||
@@ -45,8 +46,10 @@ export async function runCmd(commands, throwErrors = true) {
|
|||||||
if (!Array.isArray(commands)) {
|
if (!Array.isArray(commands)) {
|
||||||
commands = [commands];
|
commands = [commands];
|
||||||
}
|
}
|
||||||
await cc.runCommands(commands);
|
await cc.toggle();
|
||||||
|
await cc.runCommands(commands, false);
|
||||||
const lastOutput = cc.lastLogOutput;
|
const lastOutput = cc.lastLogOutput;
|
||||||
|
await cc.toggle();
|
||||||
if (throwErrors && lastOutput.includes('Error')) {
|
if (throwErrors && lastOutput.includes('Error')) {
|
||||||
throw new Error(`Error occurred while running commands: "${commands.join('; ')}" - ${lastOutput}`);
|
throw new Error(`Error occurred while running commands: "${commands.join('; ')}" - ${lastOutput}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,20 +23,21 @@ module('Integration | Component | console/ui panel', function (hooks) {
|
|||||||
|
|
||||||
test('it clears console input on enter', async function (assert) {
|
test('it clears console input on enter', async function (assert) {
|
||||||
await render(hbs`{{console/ui-panel}}`);
|
await render(hbs`{{console/ui-panel}}`);
|
||||||
|
await component.runCommands('list this/thing/here', false);
|
||||||
await component.runCommands('list this/thing/here');
|
|
||||||
await settled();
|
await settled();
|
||||||
assert.strictEqual(component.consoleInputValue, '', 'empties input field on enter');
|
assert.strictEqual(component.consoleInputValue, '', 'empties input field on enter');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it clears the log when using clear command', async function (assert) {
|
test('it clears the log when using clear command', async function (assert) {
|
||||||
await render(hbs`{{console/ui-panel}}`);
|
await render(hbs`{{console/ui-panel}}`);
|
||||||
|
await component.runCommands(
|
||||||
await component.runCommands(['list this/thing/here', 'list this/other/thing', 'read another/thing']);
|
['list this/thing/here', 'list this/other/thing', 'read another/thing'],
|
||||||
|
false
|
||||||
|
);
|
||||||
await settled();
|
await settled();
|
||||||
assert.notEqual(component.logOutput, '', 'there is output in the log');
|
assert.notEqual(component.logOutput, '', 'there is output in the log');
|
||||||
|
|
||||||
await component.runCommands('clear');
|
await component.runCommands('clear', false);
|
||||||
await settled();
|
await settled();
|
||||||
await component.up();
|
await component.up();
|
||||||
await settled();
|
await settled();
|
||||||
@@ -51,7 +52,7 @@ module('Integration | Component | console/ui panel', function (hooks) {
|
|||||||
test('it adds command to history on enter', async function (assert) {
|
test('it adds command to history on enter', async function (assert) {
|
||||||
await render(hbs`{{console/ui-panel}}`);
|
await render(hbs`{{console/ui-panel}}`);
|
||||||
|
|
||||||
await component.runCommands('list this/thing/here');
|
await component.runCommands('list this/thing/here', false);
|
||||||
await settled();
|
await settled();
|
||||||
await component.up();
|
await component.up();
|
||||||
await settled();
|
await settled();
|
||||||
@@ -67,8 +68,7 @@ module('Integration | Component | console/ui panel', function (hooks) {
|
|||||||
|
|
||||||
test('it cycles through history with more than one command', async function (assert) {
|
test('it cycles through history with more than one command', async function (assert) {
|
||||||
await render(hbs`{{console/ui-panel}}`);
|
await render(hbs`{{console/ui-panel}}`);
|
||||||
|
await component.runCommands(['list this/thing/here', 'read that/thing/there', 'qwerty'], false);
|
||||||
await component.runCommands(['list this/thing/here', 'read that/thing/there', 'qwerty']);
|
|
||||||
await settled();
|
await settled();
|
||||||
await component.up();
|
await component.up();
|
||||||
await settled();
|
await settled();
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ module('Integration | Component | sidebar-frame', function (hooks) {
|
|||||||
assert.dom('[data-test-sidebar-nav]').doesNotExist('Sidebar is hidden');
|
assert.dom('[data-test-sidebar-nav]').doesNotExist('Sidebar is hidden');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it should render link status, console ui panel and yield block for app content', async function (assert) {
|
test('it should render link status, console ui panel container and yield block for app content', async function (assert) {
|
||||||
const currentCluster = this.owner.lookup('service:currentCluster');
|
const currentCluster = this.owner.lookup('service:currentCluster');
|
||||||
currentCluster.setCluster({ hcpLinkStatus: 'connected' });
|
currentCluster.setCluster({ hcpLinkStatus: 'connected' });
|
||||||
const version = this.owner.lookup('service:version');
|
const version = this.owner.lookup('service:version');
|
||||||
@@ -50,7 +50,7 @@ module('Integration | Component | sidebar-frame', function (hooks) {
|
|||||||
`);
|
`);
|
||||||
|
|
||||||
assert.dom('[data-test-link-status]').exists('Link status component renders');
|
assert.dom('[data-test-link-status]').exists('Link status component renders');
|
||||||
assert.dom('[data-test-component="console/ui-panel"]').exists('Console UI panel renders');
|
assert.dom('[data-test-console-panel]').exists('Console UI panel container renders');
|
||||||
assert.dom('.page-container').exists('Block yields for app content');
|
assert.dom('.page-container').exists('Block yields for app content');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import keys from 'core/utils/key-codes';
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
toggle: clickable('[data-test-console-toggle]'),
|
toggle: clickable('[data-test-console-toggle]'),
|
||||||
|
dismissConsole: clickable(['data-test-dismiss-console-button']),
|
||||||
consoleInput: fillable('[data-test-component="console/command-input"] input'),
|
consoleInput: fillable('[data-test-component="console/command-input"] input'),
|
||||||
consoleInputValue: value('[data-test-component="console/command-input"] input'),
|
consoleInputValue: value('[data-test-component="console/command-input"] input'),
|
||||||
logOutput: text('[data-test-component="console/output-log"]'),
|
logOutput: text('[data-test-component="console/output-log"]'),
|
||||||
@@ -54,12 +55,18 @@ export default {
|
|||||||
eventProperties: { keyCode: keys.ENTER },
|
eventProperties: { keyCode: keys.ENTER },
|
||||||
}),
|
}),
|
||||||
hasInput: isPresent('[data-test-component="console/command-input"] input'),
|
hasInput: isPresent('[data-test-component="console/command-input"] input'),
|
||||||
runCommands: async function (commands) {
|
runCommands: async function (commands, shouldToggle = true) {
|
||||||
const toExecute = Array.isArray(commands) ? commands : [commands];
|
const toExecute = Array.isArray(commands) ? commands : [commands];
|
||||||
|
if (shouldToggle) {
|
||||||
|
await this.toggle(); // toggle the console open
|
||||||
|
}
|
||||||
for (const command of toExecute) {
|
for (const command of toExecute) {
|
||||||
await this.consoleInput(command);
|
await this.consoleInput(command);
|
||||||
await this.enter();
|
await this.enter();
|
||||||
await settled();
|
await settled();
|
||||||
}
|
}
|
||||||
|
if (shouldToggle) {
|
||||||
|
await this.toggle(); // toggle it closed
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user