[UI][VAULT-40916] Update page headers ui/app/components (#11104) (#11417)

* Update page headers for database components

* Update generate forms and license info

* Mount backend form page headers..

* Raft page headers

* Update role-aws-edit page header

* Tools, role-ssh, mount-backend-form and fix tests

* OIDC, TOTP and userpass page headers and tsts

* odic, keymgmt, and dashboard

* Fix dashboard title tests

* Fix breadcrumbs

* MFA, idenitity, and generated item

* Fix mfa enforcement page header tests

* Move tabs out of page header

Co-authored-by: Kianna <30884335+kiannaquach@users.noreply.github.com>
This commit is contained in:
Vault Automation 2025-12-18 09:29:04 -07:00 committed by GitHub
parent 49974cb486
commit 601e2cea29
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
84 changed files with 596 additions and 659 deletions

View file

@ -2,24 +2,11 @@
Copyright IBM Corp. 2016, 2025
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Page::Header @title={{this.title}}>
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-secret-header="true">
{{#if (eq @mode "create")}}
Create Alphabet
{{else if (eq @mode "edit")}}
Edit Alphabet
{{else}}
Alphabet
<code>{{@model.id}}</code>
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
</:breadcrumbs>
</Page::Header>
{{#if (eq @mode "show")}}
<Toolbar>

View file

@ -41,6 +41,16 @@ export default class AlphabetEditComponent extends Component {
];
}
get title() {
if (this.args?.mode === 'create') {
return 'Create Alphabet';
} else if (this.args?.mode === 'edit') {
return 'Edit Alphabet';
} else {
return this.args?.model?.id;
}
}
transition(route = 'show') {
this.errorMessage = '';
const { backend, id } = this.args.model;

View file

@ -3,15 +3,12 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3" data-test-dashboard-card-header="Vault version">
Vault
{{@version.versionDisplay}}
{{#if @version.isEnterprise}}
<Hds::Badge @text={{this.namespace.currentNamespace}} @icon="org" data-test-badge-namespace />
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="Vault {{@version.versionDisplay}}">
<:badges>
{{#if @version.isEnterprise}}
<Hds::Badge @text={{this.namespace.currentNamespace}} @icon="org" data-test-badge-namespace />
{{/if}}
</:badges>
</Page::Header>
<hr class="has-top-margin-xxs has-bottom-margin-l has-background-gray-200" />

View file

@ -3,22 +3,11 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Page::Header @title={{this.title}}>
<:breadcrumbs>
<KeyValueHeader @path="vault.cluster.secrets.backend.show" @mode={{this.mode}} @root={{@root}} @showCurrent={{true}} />
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-secret-header="true">
{{#if (eq @mode "create")}}
Create Connection
{{else if (eq @mode "edit")}}
Edit Connection
{{else}}
{{@model.id}}
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
</:breadcrumbs>
</Page::Header>
{{#if @model.isAvailablePlugin}}
{{#if (eq @mode "show")}}

View file

@ -33,6 +33,16 @@ export default class DatabaseConnectionEdit extends Component {
@tracked
showSaveModal = false; // used for create mode
get title() {
if (this.args?.mode === 'create') {
return 'Create Connection';
} else if (this.args?.mode === 'edit') {
return 'Edit Connection';
} else {
return this.args?.model?.id;
}
}
rotateCredentials(backend, name) {
const adapter = this.store.adapterFor('database/connection');
return adapter.rotateRootCredentials(backend, name);

View file

@ -2,22 +2,13 @@
Copyright IBM Corp. 2016, 2025
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Page::Header @title={{this.title}}>
<:breadcrumbs>
<KeyValueHeader @path="vault.cluster.secrets.backend.show" @mode={{@mode}} @root={{@root}} @showCurrent={{true}} />
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-secret-header="true">
{{#if (eq @mode "create")}}
Create Role
{{else if (eq @mode "edit")}}
Edit Role
{{else}}
{{@model.id}}
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
</:breadcrumbs>
</Page::Header>
{{#if (eq @mode "show")}}
<Toolbar>
<ToolbarActions>

View file

@ -57,6 +57,16 @@ export default class DatabaseRoleEdit extends Component {
this.modelValidations = null;
}
get title() {
if (this.args?.mode === 'create') {
return 'Create Role';
} else if (this.args?.mode === 'edit') {
return 'Edit Role';
} else {
return this.args?.model?.id;
}
}
get warningMessages() {
const warnings = {};
const { canCreateDynamic, canCreateStatic, type } = this.args.model;

View file

@ -3,23 +3,11 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Hds::Breadcrumb>
<Hds::Breadcrumb::Item
@text={{@backendPath}}
@route="vault.cluster.secrets.backend.overview"
@model={{@backendPath}}
/>
<Hds::Breadcrumb::Item @text={{@roleName}} @current={{true}} />
</Hds::Breadcrumb>
</p.top>
<p.levelLeft>
<h1 data-test-title class="title is-3">
{{@roleName}}
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title={{@roleName}}>
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</:breadcrumbs>
</Page::Header>
<div class={{if @roleType "box is-fullwidth is-sideless is-marginless"}}>
{{! If no role type, that means both static and dynamic requests returned an error }}

View file

@ -22,6 +22,16 @@ import Component from '@glimmer/component';
import { action } from '@ember/object';
export default class GenerateCredentialsDatabase extends Component {
get breadcrumbs() {
return [
{
label: this.args.backendPath,
route: 'vault.cluster.secrets.backend.overview',
model: this.args.backendPath,
},
{ label: this.args.roleName },
];
}
get errorTitle() {
return this.args.model.errorTitle || 'Something went wrong';
}

View file

@ -3,25 +3,11 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Hds::Breadcrumb>
<Hds::Breadcrumb::Item
@text={{@backendPath}}
@route="vault.cluster.secrets.backend"
@model={{@backendPath}}
data-test-link="role-list"
/>
<Hds::Breadcrumb::Item @text={{@keyName}} @route="vault.cluster.secrets.backend.show" @model={{@keyName}} />
<Hds::Breadcrumb::Item @text={{this.title}} @current={{true}} />
</Hds::Breadcrumb>
</p.top>
<p.levelLeft>
<h1 data-test-title class="title is-3">
{{this.title}}
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title={{this.title}}>
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</:breadcrumbs>
</Page::Header>
<div class="box is-fullwidth is-sideless is-paddingless is-marginless">
<InfoTableRow @label="Code">

View file

@ -24,6 +24,18 @@ export default class GenerateCredentialsTotp extends Component {
this.startTimer.perform();
}
get breadcrumbs() {
return [
{
label: this.args.backendPath,
route: 'vault.cluster.secrets.backend',
model: this.args.backendPath,
},
{ label: this.args.keyName, route: 'vault.cluster.secrets.backend.show', model: this.args.keyName },
{ label: this.title },
];
}
get remainingTime() {
const { totpCodePeriod } = this.args;

View file

@ -3,26 +3,11 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Hds::Breadcrumb>
<Hds::Breadcrumb::Item
@text={{@backendPath}}
@route="vault.cluster.secrets.backend"
@model={{@backendPath}}
data-test-link="role-list"
/>
<Hds::Breadcrumb::Item @text="Credentials" @route="vault.cluster.secrets.backend" @model={{@backendPath}} />
<Hds::Breadcrumb::Item @text={{@roleName}} @route="vault.cluster.secrets.backend.show" @model={{@roleName}} />
<Hds::Breadcrumb::Item @text={{this.options.title}} @current={{true}} />
</Hds::Breadcrumb>
</p.top>
<p.levelLeft>
<h1 data-test-title class="title is-3">
{{this.options.title}}
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title={{this.options.title}}>
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</:breadcrumbs>
</Page::Header>
{{#if this.hasGenerated}}
<div class="box is-fullwidth is-sideless is-paddingless is-marginless">

View file

@ -89,6 +89,19 @@ export default class GenerateCredentials extends Component<Args> {
return undefined;
}
get breadcrumbs() {
return [
{
label: this.args.backendPath,
route: 'vault.cluster.secrets.backend',
model: this.args.backendPath,
},
{ label: 'Credentials', route: 'vault.cluster.secrets.backend', model: this.args.backendPath },
{ label: this.args.roleName, route: 'vault.cluster.secrets.backend.show', model: this.args.roleName },
{ label: this.options.title },
];
}
get helpText(): string {
let message = '';
if (this.cannotReadAwsRole) {

View file

@ -3,19 +3,12 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Hds::Breadcrumb>
<Hds::Breadcrumb::Item @text="Auth Methods" @route="vault.cluster.access.methods" data-test-access-methods />
<Hds::Breadcrumb::Item @text={{@methodModel.id}} @current={{true}} />
</Hds::Breadcrumb>
</p.top>
<p.levelLeft>
<h1 class="title is-3">
{{@methodModel.id}}
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title={{@methodModel.id}}>
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</:breadcrumbs>
</Page::Header>
{{#let (tabs-for-auth-section @methodModel "authConfig" @paths) as |tabs|}}
{{#if tabs.length}}
<div class="tabs-container box is-sideless is-fullwidth is-paddingless is-marginless">

View file

@ -29,6 +29,16 @@ export default class GeneratedItemList extends Component {
@service pagination;
@tracked itemToDelete = null;
get breadcrumbs() {
return [
{
label: 'Auth Methods',
route: 'vault.cluster.access.methods',
},
{ label: this.args.methodModel.id },
];
}
@action
refreshItemList() {
const route = getOwner(this).lookup(`route:${this.router.currentRouteName}`);

View file

@ -3,33 +3,21 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Hds::Breadcrumb>
<Hds::Breadcrumb::Item
@text={{pluralize this.itemType}}
@route="vault.cluster.access.method.item.list"
@models={{array this.mountPath this.itemType}}
/>
<Hds::Breadcrumb::Item @text={{if (eq this.mode "show") this.model.id (capitalize this.mode)}} @current={{true}} />
</Hds::Breadcrumb>
</p.top>
<p.levelLeft>
{{#if (eq this.mode "show")}}
<h1 class="title is-3">
{{this.model.id}}
</h1>
{{else}}
<h1 class="title is-3">
{{capitalize this.mode}}
{{singularize this.itemType}}
{{#if (eq this.mode "edit")}}
{{this.model.id}}
{{/if}}
</h1>
{{/if}}
</p.levelLeft>
</PageHeader>
<Page::Header @title={{this.title}}>
<:breadcrumbs>
<Page::Breadcrumbs
@breadcrumbs={{array
(hash
label=(pluralize this.itemType)
route="vault.cluster.access.method.item.list"
models=(array this.mountPath this.itemType)
)
(hash label=(if (eq this.mode "show") this.model.id (capitalize this.mode)))
}}
/>
</:breadcrumbs>
</Page::Header>
{{#if (eq this.mode "show")}}
<Toolbar>
<ToolbarActions>

View file

@ -9,6 +9,8 @@ import Component from '@ember/component';
import { computed } from '@ember/object';
import { task } from 'ember-concurrency';
import { waitFor } from '@ember/test-waiters';
import { capitalize } from '@ember/string';
import { singularize } from 'ember-inflector';
/**
* @module GeneratedItem
@ -35,6 +37,18 @@ export default Component.extend({
props: computed('model', function () {
return this.model.serialize();
}),
get title() {
const title = `${capitalize(this.mode)} ${singularize(this.itemType)}`;
if (this.mode === 'show') {
return this.model.id;
} else if (this.mode === 'edit') {
return `${title} ${this.model.id}`;
}
return `${capitalize(this.mode)} ${singularize(this.itemType)}`;
},
validateForm() {
// Only validate on new models because blank passwords will not be updated
// in practice this only happens for userpass users

View file

@ -3,29 +3,23 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3">
{{titleize (pluralize this.identityType)}}
</h1>
</p.levelLeft>
</PageHeader>
<div class="tabs-container box is-sideless is-fullwidth is-paddingless is-marginless">
<nav class="tabs" aria-label="navigation for entities">
<ul>
<li>
<LinkTo @route="vault.cluster.access.identity.index" @model={{pluralize this.identityType}}>
{{capitalize (pluralize this.identityType)}}
</LinkTo>
</li>
<li>
<LinkTo @route="vault.cluster.access.identity.aliases.index" @model={{pluralize this.identityType}}>
Aliases
</LinkTo>
</li>
</ul>
</nav>
</div>
<Page::Header @title={{titleize (pluralize this.identityType)}} />
<nav class="tabs" aria-label="navigation for entities">
<ul>
<li>
<LinkTo @route="vault.cluster.access.identity.index" @model={{pluralize this.identityType}}>
{{capitalize (pluralize this.identityType)}}
</LinkTo>
</li>
<li>
<LinkTo @route="vault.cluster.access.identity.aliases.index" @model={{pluralize this.identityType}}>
Aliases
</LinkTo>
</li>
</ul>
</nav>
<Toolbar>
{{#if this.model.meta.total}}
<ToolbarFilters>

View file

@ -3,24 +3,11 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Page::Header @title={{this.title}}>
<:breadcrumbs>
<KeyValueHeader @path="vault.cluster.secrets.backend.show" @mode={{this.mode}} @root={{@root}} @showCurrent={{true}} />
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-secret-header="true">
{{#if this.isDistributing}}
Distribute Key
{{else if (eq @mode "create")}}
Create Key
{{else if (eq @mode "edit")}}
Edit Key
{{else}}
{{@model.id}}
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
</:breadcrumbs>
</Page::Header>
{{#if this.isDistributing}}
<Keymgmt::Distribute @backend={{@model.backend}} @key={{@model.id}} @onClose={{fn (mut this.isDistributing) false}} />

View file

@ -31,6 +31,17 @@ export default class KeymgmtKeyEdit extends Component {
@service flashMessages;
@tracked isDeleteModalOpen = false;
get title() {
if (this.isDistributing) {
return 'Distribute Key';
} else if (this.args.mode === 'create') {
return 'Create Key';
} else if (this.args.mode === 'edit') {
return 'Edit Key';
}
return this.args.model.id;
}
get mode() {
return this.args.mode || 'show';
}

View file

@ -3,23 +3,11 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Page::Header @title={{this.title}} @subtitle={{this.subtitle}}>
<:breadcrumbs>
<KeyValueHeader @path="vault.cluster.secrets.backend.show" @mode={{@mode}} @root={{@root}} @showCurrent={{true}} />
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-kms-provider-header>
{{#if this.isDistributing}}
Distribute Key to Provider
{{else if this.isShowing}}
Provider
<span class="has-font-weight-normal">{{@model.id}}</span>
{{else}}
{{if this.isCreating "Create Provider" "Update Credentials"}}
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
</:breadcrumbs>
</Page::Header>
{{#if this.isDistributing}}
<Keymgmt::Distribute @backend={{@model.backend}} @provider={{@model.id}} @onClose={{fn (mut this.isDistributing) false}} />

View file

@ -38,6 +38,22 @@ export default class KeymgmtProviderEdit extends Component {
@tracked modelValidations;
get title() {
if (this.isDistributing) {
return 'Distribute Key to Provider';
} else if (this.isShowing) {
return 'Provider';
} else if (this.isCreating) {
return 'Create Provider';
}
return 'Update Credentials';
}
get subtitle() {
return this.isShowing ? this.args.model.id : '';
}
get isShowing() {
return this.args.mode === 'show';
}

View file

@ -3,11 +3,7 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3">License</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="License" />
<section class="box is-sideless is-marginless is-shadowless is-fullwidth">
<span class="title is-5">Details</span>

View file

@ -3,26 +3,11 @@
SPDX-License-Identifier: BUSL-1.1
}}
{{#if @isInline}}
<h3 class="title is-5" data-test-mleh-title>Enforcement</h3>
{{else}}
<PageHeader as |p|>
<p.top>
<Hds::Breadcrumb>
<Hds::Breadcrumb::Item @text="Enforcements" @route="vault.cluster.access.mfa.enforcements.index" />
<Hds::Breadcrumb::Item @text={{@heading}} @current={{true}} />
</Hds::Breadcrumb>
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-mleh-title>
<Icon @name="lock" @size="24" />
{{@heading}}
</h1>
</p.levelLeft>
</PageHeader>
{{/if}}
<div class="has-border-top-light">
<p class="has-top-margin-m" data-test-mleh-description>
<Page::Header @title={{if @isInline "Enforcement" @heading}} @icon={{unless @isInline "lock"}}>
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</:breadcrumbs>
<:description>
{{#if @isInline}}
An enforcement includes the authentication types, authentication methods, groups, and entities that will require this
MFA method. This is optional and can be added later.
@ -32,7 +17,10 @@
all entities and groups which make use of that authentication method will be subject to an MFA request.
<DocLink @path="/vault/docs/auth/login-mfa">Learn more here.</DocLink>
{{/if}}
</p>
</:description>
</Page::Header>
<div class="has-border-top-light has-top-bottom-margin">
{{#if @isInline}}
<div class="is-flex-row">
<RadioCard

View file

@ -38,6 +38,18 @@ export default class MfaLoginEnforcementHeaderComponent extends Component {
@tracked enforcements = [];
get breadcrumbs() {
return [
{
label: 'Enforcements',
route: 'vault.cluster.access.mfa.enforcements.index',
},
{
label: this.args.heading,
},
];
}
async fetchEnforcements() {
try {
// cache initial values for lookup in select handler

View file

@ -3,28 +3,9 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3 title-with-icon" data-test-page-title>
{{#if this.showEnable}}
{{#let (find-by "type" this.mountForm.type @mountTypes) as |typeInfo|}}
{{#if typeInfo.glyph}}
<Icon @name={{typeInfo.glyph}} @size="24" class="has-text-grey-light" />
{{/if}}
{{#if (eq @mountCategory "secret")}}
{{concat "Enable " (or typeInfo.displayName this.mountForm.type) " Secrets Engine"}}
{{else}}
{{concat "Enable " (or typeInfo.displayName this.mountForm.type) " Authentication Method"}}
{{/if}}
{{/let}}
{{else if (eq @mountCategory "secret")}}
Enable a Secrets Engine
{{else}}
Enable an Authentication Method
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
{{#let (find-by "type" this.mountForm.type @mountTypes) as |typeInfo|}}
<Page::Header @icon={{typeInfo.glyph}} @title={{this.title}} />
{{/let}}
<div class="box is-sideless is-bottomless is-fullwidth is-marginless">
<NamespaceReminder @mode="enable" @noun={{if (eq @mountCategory "secret") "Secret Engine" "Auth Method"}} />

View file

@ -32,8 +32,14 @@ import type { ValidationMap } from 'vault/vault/app-types';
*
*/
interface TypeInfo {
type: string;
displayName: string;
glyph: string;
}
interface Args {
mountModel: AuthMethodForm;
mountTypes: TypeInfo[] | undefined;
onMountSuccess: (type: string, path: string, useEngineRoute: boolean) => void;
}
@ -59,6 +65,16 @@ export default class MountBackendForm extends Component<Args> {
return !!this.mountForm.type;
}
get title(): string {
const typeInfo = (this.args?.mountTypes || []).find(
(mountType: TypeInfo) => this.mountForm.type === mountType.type
);
if (this.showEnable) {
return `Enable ${typeInfo?.displayName || this.mountForm.type} Authentication Method`;
}
return 'Enable an Authentication Method';
}
constructor(owner: unknown, args: Args) {
super(owner, args);
}

View file

@ -4,16 +4,11 @@
}}
<div class="box is-sideless is-fullwidth is-marginless is-bottomless">
<Hds::PageHeader class="page-header" as |PH|>
<PH.Breadcrumb>
<Hds::Breadcrumb data-test-breadcrumbs>
<Hds::Breadcrumb::Item @text="Secrets engines" @route="vault.cluster.secrets.backends" />
<Hds::Breadcrumb::Item @text="Enable secrets engine" @route="vault.cluster.secrets.enable" />
<Hds::Breadcrumb::Item @text={{capitalize @model.type}} @current={{true}} />
</Hds::Breadcrumb>
</PH.Breadcrumb>
</Hds::PageHeader>
<Page::Header>
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</:breadcrumbs>
</Page::Header>
<MessageError @errorMessage={{this.errorMessage}} />

View file

@ -9,6 +9,8 @@ import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import { task } from 'ember-concurrency';
import { set } from '@ember/object';
import { capitalize } from '@ember/string';
import type FlashMessagesService from 'ember-cli-flash/services/flash-messages';
import type ApiService from 'vault/services/api';
import type CapabilitiesService from 'vault/services/capabilities';
@ -41,6 +43,19 @@ export default class MountSecretsEngineFormComponent extends Component<Args> {
@tracked invalidFormAlert: string | null = null;
@tracked errorMessage: string | string[] = '';
get breadcrumbs() {
const breadcrumbs: { label: string; route?: string }[] = [
{ label: 'Secrets engines', route: 'vault.cluster.secrets.backends' },
{ label: 'Enable secrets engine', route: 'vault.cluster.secrets.enable' },
];
if (this.args?.model.type) {
breadcrumbs.push({ label: capitalize(this.args?.model?.type) });
}
return breadcrumbs;
}
get mountForm(): SecretsEngineForm {
return this.args.model;
}

View file

@ -4,13 +4,8 @@
}}
<div class="box is-shadowless" data-test-not-found>
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3 has-text-grey">
404 Not Found
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="404 Not Found" />
<div class="box is-sideless has-background-white-bis has-text-grey has-text-centered">
<p>Sorry, we were unable to find any content at <code>{{or @model.path this.path}}</code>.</p>
<p>

View file

@ -3,28 +3,12 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Hds::Breadcrumb>
{{#if @model.isNew}}
<Hds::Breadcrumb::Item @text="Applications" @route="vault.cluster.access.oidc.clients" />
{{else}}
<Hds::Breadcrumb::Item
@text="Details"
@route="vault.cluster.access.oidc.clients.client.details"
@model={{@model.name}}
/>
{{/if}}
<Hds::Breadcrumb::Item @text="{{if @model.isNew 'Create' 'Edit'}} Application" @current={{true}} />
</Hds::Breadcrumb>
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-oidc-client-title>
{{if @model.isNew "Create" "Edit"}}
Application
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="{{if @model.isNew 'Create' 'Edit'}} Application">
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</:breadcrumbs>
</Page::Header>
<form {{on "submit" (perform this.save)}}>
<div class="box is-sideless is-fullwidth is-bottomless">
<MessageError @errorMessage={{this.errorBanner}} />

View file

@ -32,6 +32,17 @@ export default class OidcClientForm extends Component {
? 'allow_all'
: 'limited';
get breadcrumbs() {
const firstBreadcrumb = this.args.model.isNew
? { label: 'Applications', route: 'vault.cluster.access.oidc.clients' }
: {
label: 'Details',
route: 'vault.cluster.access.oidc.clients.client.details',
model: this.args.model.name,
};
return [firstBreadcrumb, { label: this.args.model.isNew ? 'Create Application' : 'Edit Application' }];
}
get modelAssignments() {
const { assignments } = this.args.model;
if (assignments.includes('allow_all') && assignments.length === 1) {

View file

@ -3,28 +3,11 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Hds::Breadcrumb>
{{#if @model.isNew}}
<Hds::Breadcrumb::Item @text="Providers" @route="vault.cluster.access.oidc.providers" />
{{else}}
<Hds::Breadcrumb::Item
@text="Details"
@route="vault.cluster.access.oidc.providers.provider.details"
@model={{@model.name}}
/>
{{/if}}
<Hds::Breadcrumb::Item @text="{{if @model.isNew 'Create' 'Edit'}} Provider" @current={{true}} />
</Hds::Breadcrumb>
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-oidc-provider-title>
{{if @model.isNew "Create" "Edit"}}
Provider
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="{{if @model.isNew 'Create' 'Edit'}} Provider">
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</:breadcrumbs>
</Page::Header>
<form {{on "submit" (perform this.save)}} {{did-insert this.setIssuer @model}}>
<div class="box is-sideless is-fullwidth is-bottomless">

View file

@ -36,6 +36,17 @@ export default class OidcProviderForm extends Component {
? 'allow_all'
: 'limited';
get breadcrumbs() {
const firstBreadcrumb = this.args.model.isNew
? { label: 'Providers', route: 'vault.cluster.access.oidc.providers' }
: {
label: 'Details',
route: 'vault.cluster.access.oidc.providers.provider.details',
model: this.args.model.name,
};
return [firstBreadcrumb, { label: this.args.model.isNew ? 'Create Provider' : 'Edit Provider' }];
}
// function passed to search select
renderTooltip(selection, dropdownOptions) {
// if a client has been deleted it will not exist in dropdownOptions (response from search select's query)

View file

@ -3,28 +3,11 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Hds::Breadcrumb>
{{#if @model.isNew}}
<Hds::Breadcrumb::Item @text="Scopes" @route="vault.cluster.access.oidc.scopes" />
{{else}}
<Hds::Breadcrumb::Item
@text="Details"
@route="vault.cluster.access.oidc.scopes.scope.details"
@model={{@model.name}}
/>
{{/if}}
<Hds::Breadcrumb::Item @text="{{if @model.isNew 'Create' 'Edit'}} Scope" @current={{true}} />
</Hds::Breadcrumb>
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-oidc-scope-title>
{{if @model.isNew "Create" "Edit"}}
Scope
</h1>
</p.levelLeft>
<p.levelRight>
<Page::Header @title="{{if @model.isNew 'Create' 'Edit'}} Scope">
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</:breadcrumbs>
<:actions>
<Hds::Button
@text="How to write JSON template for scopes"
@icon="bulb"
@ -32,8 +15,8 @@
{{on "click" (fn (mut this.showTemplateModal))}}
data-test-oidc-scope-example
/>
</p.levelRight>
</PageHeader>
</:actions>
</Page::Header>
<form {{on "submit" (perform this.save)}}>
<div class="box is-sideless is-fullwidth is-marginless">

View file

@ -39,6 +39,17 @@ export default class OidcScopeFormComponent extends Component {
"groups": {{identity.entity.groups.names}}
}`;
get breadcrumbs() {
const firstBreadcrumb = this.args.model.isNew
? { label: 'Scopes', route: 'vault.cluster.access.oidc.scopes' }
: {
label: 'Details',
route: 'vault.cluster.access.oidc.scopes.scope.details',
model: this.args.model.name,
};
return [firstBreadcrumb, { label: this.args.model.isNew ? 'Create Scope' : 'Edit Scope' }];
}
@task
*save(event) {
event.preventDefault();

View file

@ -3,13 +3,7 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.levelLeft>
<h1 data-test-title class="title is-3">
Reset password
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="Reset password" />
<form {{on "submit" (perform this.updatePassword) on="submit"}}>
<div class="box is-sideless is-fullwidth is-marginless">

View file

@ -3,19 +3,13 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Hds::Breadcrumb>
<Hds::Breadcrumb::Item @text="Raft Storage" @route="vault.cluster.storage" />
<Hds::Breadcrumb::Item @text="Restore Snapshot" @current={{true}} />
</Hds::Breadcrumb>
</p.top>
<p.levelLeft>
<h1 class="title is-3">
Restore Snapshot
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="Restore Snapshot">
<:breadcrumbs>
<Page::Breadcrumbs
@breadcrumbs={{array (hash label="Raft Storage" route="vault.cluster.storage") (hash label="Restore Snapshot")}}
/>
</:breadcrumbs>
</Page::Header>
<form {{action (perform this.restore this.file) on="submit"}}>
<MessageError @errors={{this.errors}} />

View file

@ -3,8 +3,8 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Page::Header @title={{this.title}} @subtitle={{this.subtitle}}>
<:breadcrumbs>
<KeyValueHeader
@baseKey={{this.model}}
@path="vault.cluster.secrets.backend.list"
@ -12,21 +12,8 @@
@root={{this.root}}
@showCurrent={{true}}
/>
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-secret-header="true">
{{#if (eq this.mode "create")}}
Create an AWS Role
{{else if (eq this.mode "edit")}}
Edit AWS Role
<code>{{this.model.id}}</code>
{{else}}
AWS Role
<code>{{this.model.id}}</code>
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
</:breadcrumbs>
</Page::Header>
{{#if (eq this.mode "show")}}
<Toolbar>

View file

@ -6,9 +6,26 @@
import { isBlank } from '@ember/utils';
import { set } from '@ember/object';
import RoleEdit from './role-edit';
import { computed } from '@ember/object';
const SHOW_ROUTE = 'vault.cluster.secrets.backend.show';
export default RoleEdit.extend({
title: computed('mode', function () {
if (this.mode === 'create') {
return 'Create an AWS Role';
} else if (this.mode === 'edit') {
return 'Edit AWS Role';
} else {
return 'AWS Role';
}
}),
subtitle: computed('mode', 'model.id', function () {
if (this.mode === 'create') return;
return this.model.id;
}),
actions: {
createOrUpdate(type, event) {
event.preventDefault();

View file

@ -3,8 +3,8 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Page::Header @title={{this.title}} @subtitle={{this.subtitle}}>
<:breadcrumbs>
<KeyValueHeader
@baseKey={{this.model}}
@path="vault.cluster.secrets.backend.list"
@ -12,20 +12,8 @@
@root={{this.root}}
@showCurrent={{true}}
/>
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-secret-header="true">
{{#if (eq this.mode "create")}}
Create an SSH Role
{{else if (eq this.mode "edit")}}
Edit SSH Role
{{else}}
SSH Role
<code>{{this.model.id}}</code>
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
</:breadcrumbs>
</Page::Header>
{{#if (eq this.mode "show")}}
<Toolbar>

View file

@ -4,6 +4,7 @@
*/
import RoleEdit from './role-edit';
import { computed } from '@ember/object';
export default RoleEdit.extend({
init() {
@ -11,6 +12,22 @@ export default RoleEdit.extend({
this.set('backendType', 'ssh');
},
title: computed('mode', function () {
if (this.mode === 'create') {
return 'Create SSH Role';
} else if (this.mode === 'edit') {
return 'Edit SSH Role';
} else {
return 'SSH Role';
}
}),
subtitle: computed('mode', 'model.id', function () {
if (this.mode === 'create' || this.mode === 'edit') return;
return this.model.id;
}),
actions: {
updateTtl(path, val) {
const model = this.model;

View file

@ -11,16 +11,6 @@
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{@breadcrumbs}} />
</:breadcrumbs>
<:tabs>
<Mount::ConfigureTabs
@configRoute={{if
engineDisplayData.isConfigurable
(or engineDisplayData.configRoute "configuration.plugin-settings")
}}
@displayName={{engineDisplayData.displayName}}
@path={{@model.secretsEngine.id}}
/>
</:tabs>
<:actions>
<Hds::Button
@color="secondary"
@ -34,8 +24,12 @@
/>
</:actions>
</Page::Header>
<Mount::ConfigureTabs
@configRoute={{if engineDisplayData.isConfigurable (or engineDisplayData.configRoute "configuration.plugin-settings")}}
@displayName={{engineDisplayData.displayName}}
@path={{@model.secretsEngine.id}}
/>
{{/let}}
{{#if this.saveGeneralSettings.isRunning}}
{{! TODO: Fix loading state styles }}
<Hds::Layout::Flex @gap="24" @direction="column" @justify="center" @align="center">

View file

@ -12,13 +12,6 @@
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{@breadcrumbs}} />
</:breadcrumbs>
<:tabs>
<Mount::ConfigureTabs
@configRoute={{or engineDisplayData.configRoute "configuration.plugin-settings"}}
@displayName={{engineDisplayData.displayName}}
@path={{@model.secretsEngine.id}}
/>
</:tabs>
<:actions>
<Hds::Button
@color="secondary"
@ -32,6 +25,11 @@
/>
</:actions>
</Page::Header>
<Mount::ConfigureTabs
@configRoute={{or engineDisplayData.configRoute "configuration.plugin-settings"}}
@displayName={{engineDisplayData.displayName}}
@path={{@model.secretsEngine.id}}
/>
{{#if @model.config}}
<Toolbar>

View file

@ -3,13 +3,7 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3">
Hash Data
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="Hash Data" />
{{#if this.sum}}
<div class="box is-sideless is-fullwidth is-marginless">

View file

@ -3,13 +3,7 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3">
Lookup Token
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="Lookup Token" />
{{#if this.lookupData}}
<div class="box is-fullwidth is-sideless is-paddingless is-marginless">

View file

@ -3,13 +3,7 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3">
Random Bytes
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="Random Bytes" />
{{#if this.randomBytes}}
<div class="box is-sideless is-fullwidth is-marginless">

View file

@ -3,13 +3,7 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3">
Rewrap Token
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="Rewrap Token" />
{{#if this.rewrappedToken}}
<div class="box is-sideless is-fullwidth is-marginless">

View file

@ -3,13 +3,7 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3">
Unwrap Data
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="Unwrap Data" />
{{#if this.unwrapData}}
<Hds::Tabs as |T|>

View file

@ -3,13 +3,7 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3">
Wrap Data
</h1>
</p.levelLeft>
</PageHeader>
<Page::Header @title="Wrap Data" />
{{#if this.token}}
<div class="box is-sideless is-fullwidth is-marginless">

View file

@ -3,8 +3,8 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Page::Header @title={{this.title}} @subtitle={{this.subtitle}}>
<:breadcrumbs>
<KeyValueHeader
@baseKey={{@model}}
@path="vault.cluster.secrets.backend.list"
@ -12,18 +12,8 @@
@root={{@root}}
@showCurrent={{true}}
/>
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-secret-header>
{{#if (eq @mode "create")}}
Create a TOTP key
{{else}}
TOTP key
<code>{{@model.id}}</code>
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
</:breadcrumbs>
</Page::Header>
{{#if (eq @mode "show")}}
<Totp::KeyDetails @model={{@model}} @onDelete={{this.deleteKey}} />

View file

@ -34,6 +34,19 @@ export default class TotpEdit extends Component {
successCallback;
get title() {
if (this.args.mode === 'create') {
return 'Create a TOTP key';
}
return 'TOTP key';
}
get subtitle() {
if (this.args.mode === 'create') return '';
return this.args.model.id;
}
get defaultKeyFormFields() {
const shared = ['name', 'generate', 'issuer', 'accountName'];
const generated = [...shared, 'exported'];

View file

@ -3,8 +3,8 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Page::Header @title={{this.title}} @subtitle={{this.subtitle}}>
<:breadcrumbs>
<KeyValueHeader
@baseKey={{hash display=this.model.id id=this.model.idForNav}}
@path="vault.cluster.secrets.backend.list"
@ -12,20 +12,8 @@
@root={{this.root}}
@showCurrent={{true}}
/>
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-secret-header="true">
{{#if (eq this.mode "create")}}
Create Role
{{else if (eq this.mode "edit")}}
Edit Role
{{else}}
Role
<code>{{this.model.id}}</code>
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
</:breadcrumbs>
</Page::Header>
{{#if (eq this.mode "show")}}
<Toolbar>

View file

@ -5,6 +5,7 @@
import TransformBase, { addToList, removeFromList } from './transform-edit-base';
import { service } from '@ember/service';
import { computed } from '@ember/object';
export default TransformBase.extend({
flashMessages: service(),
@ -16,6 +17,22 @@ export default TransformBase.extend({
this.set('initialTransformations', this.model.transformations);
},
title: computed('mode', function () {
if (this.mode === 'create') {
return 'Create Role';
} else if (this.mode === 'edit') {
return 'Edit Role';
} else {
return 'Role';
}
}),
subtitle: computed('mode', 'model.id', function () {
if (this.mode === 'create' || this.mode === 'edit') return;
return this.model.id;
}),
handleUpdateTransformations(updateTransformations, roleId, type = 'update') {
if (!updateTransformations) return;
const backend = this.model.backend;

View file

@ -3,23 +3,11 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Page::Header @title={{this.title}} @subtitle={{this.subtitle}}>
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-secret-header="true">
{{#if (eq @mode "create")}}
Create Template
{{else if (eq @mode "edit")}}
Edit Template
{{else}}
Template
<code>{{@model.id}}</code>
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
</:breadcrumbs>
</Page::Header>
{{#if (eq @mode "show")}}
<Toolbar>

View file

@ -41,6 +41,22 @@ export default class TransformTemplateEditComponent extends Component {
];
}
get title() {
if (this.args.mode === 'create') {
return 'Create Template';
} else if (this.args.mode === 'edit') {
return 'Edit Template';
} else {
return 'Template';
}
}
get subtitle() {
if (this.args.mode === 'create' || this.args.mode === 'edit') return '';
return this.args?.model?.id;
}
transition(route = 'show') {
this.errorMessage = '';
const { backend, id } = this.args.model;

View file

@ -3,8 +3,8 @@ Copyright IBM Corp. 2016, 2025
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Page::Header @title={{this.title}} @subtitle={{this.subtitle}}>
<:breadcrumbs>
<KeyValueHeader
@baseKey={{this.model}}
@path="vault.cluster.secrets.backend.list"
@ -12,20 +12,8 @@ SPDX-License-Identifier: BUSL-1.1
@root={{this.root}}
@showCurrent={{true}}
/>
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-secret-header="true">
{{#if (eq this.mode "create")}}
Create Transformation
{{else if (eq this.mode "edit")}}
Edit Transformation
{{else}}
Transformation
<code>{{this.model.id}}</code>
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
</:breadcrumbs>
</Page::Header>
{{#if (eq this.mode "show")}}
<Toolbar>

View file

@ -5,6 +5,7 @@
import TransformBase, { addToList, removeFromList } from './transform-edit-base';
import { service } from '@ember/service';
import { computed } from '@ember/object';
export default TransformBase.extend({
flashMessages: service(),
@ -17,6 +18,22 @@ export default TransformBase.extend({
this.set('initialRoles', this.model.allowed_roles);
},
title: computed('mode', function () {
if (this.mode === 'create') {
return 'Create Transformation';
} else if (this.mode === 'edit') {
return 'Edit Transformation';
} else {
return 'Transformation';
}
}),
subtitle: computed('mode', 'model.id', function () {
if (this.mode === 'create' || this.mode === 'edit') return;
return this.model.id;
}),
async updateOrCreateRole(role, transformationId, backend) {
const roleRecord = await this.store
.queryRecord('transform/role', {

View file

@ -3,23 +3,12 @@
SPDX-License-Identifier: BUSL-1.1
}}
<PageHeader as |p|>
<p.top>
<Page::Header @title={{this.title}} @subtitle={{this.subtitle}}>
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</p.top>
<p.levelLeft>
<h1 class="title is-3">
{{#if (eq this.mode "create")}}
Create Key
{{else if (eq this.mode "edit")}}
Edit Key
{{else}}
Key
<code>{{this.key.id}}</code>
{{/if}}
</h1>
</p.levelLeft>
</PageHeader>
</:breadcrumbs>
</Page::Header>
{{#if (eq this.mode "create")}}
<TransitFormCreate
@createOrUpdateKey={{action "createOrUpdateKey" this.mode}}

View file

@ -69,6 +69,22 @@ export default Component.extend(FocusOnInsertMixin, {
return baseCrumbs;
},
get title() {
if (this.mode === 'create') {
return 'Create Key';
} else if (this.mode === 'edit') {
return 'Edit Key';
} else {
return 'Key';
}
},
get subtitle() {
if (this.mode === 'create' || this.mode === 'edit') return '';
return this.key?.id;
},
waitForKeyUp: task(function* () {
while (true) {
const event = yield waitForEvent(document.body, 'keyup');

View file

@ -24,14 +24,12 @@
data-test-button="Exit configuration"
/>
</:actions>
<:tabs>
<Mount::ConfigureTabs
@configRoute="configuration.edit"
@displayName={{engineDisplayData.displayName}}
@path={{this.model.secretsEngine.id}}
/>
</:tabs>
</Page::Header>
<Mount::ConfigureTabs
@configRoute="configuration.edit"
@displayName={{engineDisplayData.displayName}}
@path={{this.model.secretsEngine.id}}
/>
{{/let}}
<Toolbar>

View file

@ -21,16 +21,12 @@
{{#if @subtitle}}
<PH.Subtitle>{{@subtitle}}</PH.Subtitle>
{{/if}}
{{#if @description}}
{{#if (has-block "description")}}
<PH.Description>{{yield to="description"}}</PH.Description>
{{else if @description}}
<PH.Description>{{@description}}</PH.Description>
{{/if}}
{{#if (has-block "actions")}}
<PH.Actions>{{yield to="actions"}}</PH.Actions>
{{/if}}
</Hds::PageHeader>
{{#if (has-block "tabs")}}
<div class="has-top-margin-l">
{{yield to="tabs"}}
</div>
{{/if}}
</Hds::PageHeader>

View file

@ -32,26 +32,25 @@
</Hds::Dropdown>
{{/if}}
</:actions>
<:tabs>
{{#if @configRoute}}
<Mount::ConfigureTabs
@configRoute={{@configRoute}}
@displayName="LDAP"
@path={{@model.id}}
@externalRoute="secretsGeneralSettingsConfiguration"
/>
{{else}}
<nav class="tabs" aria-label="ldap tabs">
<ul>
<li><LinkTo @route="overview" data-test-tab="overview">Overview</LinkTo></li>
<li><LinkTo @route="roles" data-test-tab="roles">Roles</LinkTo></li>
<li><LinkTo @route="libraries" data-test-tab="libraries">Libraries</LinkTo></li>
</ul>
</nav>
{{/if}}
</:tabs>
</Page::Header>
{{#if @configRoute}}
<Mount::ConfigureTabs
@configRoute={{@configRoute}}
@displayName="LDAP"
@path={{@model.id}}
@externalRoute="secretsGeneralSettingsConfiguration"
/>
{{else}}
<nav class="tabs" aria-label="ldap tabs">
<ul>
<li><LinkTo @route="overview" data-test-tab="overview">Overview</LinkTo></li>
<li><LinkTo @route="roles" data-test-tab="roles">Roles</LinkTo></li>
<li><LinkTo @route="libraries" data-test-tab="libraries">Libraries</LinkTo></li>
</ul>
</nav>
{{/if}}
{{#if this.engineToDisable}}
<ConfirmModal
@color="critical"

View file

@ -38,16 +38,15 @@
{{/if}}
</Hds::Dropdown>
</:actions>
<:tabs>
<nav class="tabs" aria-label="ldap tabs">
<ul>
<li><LinkTo @route="libraries.library.details.accounts" data-test-tab="accounts">Accounts</LinkTo></li>
<li><LinkTo @route="libraries.library.details.configuration" data-test-tab="config">Configuration</LinkTo></li>
</ul>
</nav>
</:tabs>
</Page::Header>
<nav class="tabs" aria-label="ldap tabs">
<ul>
<li><LinkTo @route="libraries.library.details.accounts" data-test-tab="accounts">Accounts</LinkTo></li>
<li><LinkTo @route="libraries.library.details.configuration" data-test-tab="config">Configuration</LinkTo></li>
</ul>
</nav>
{{#if this.showConfirmModal}}
<ConfirmModal
@color="critical"

View file

@ -7,25 +7,24 @@
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</:breadcrumbs>
<:tabs>
<nav class="tabs" aria-label="pki tabs">
<ul>
<li><LinkTo @route="overview" @model={{@backend.id}} data-test-secret-list-tab="Overview">Overview</LinkTo></li>
<li><LinkTo @route="roles" @model={{@backend.id}} data-test-secret-list-tab="Roles">Roles</LinkTo></li>
<li><LinkTo @route="issuers" @model={{@backend.id}} data-test-secret-list-tab="Issuers">Issuers</LinkTo></li>
<li><LinkTo @route="keys" @model={{@backend.id}} data-test-secret-list-tab="Keys">Keys</LinkTo></li>
<li><LinkTo
@route="certificates"
@model={{@backend.id}}
data-test-secret-list-tab="Certificates"
>Certificates</LinkTo></li>
<li><LinkTo @route="tidy" @model={{@backend.id}} data-test-secret-list-tab="Tidy">Tidy</LinkTo></li>
<li><LinkTo
@route="configuration"
@model={{@backend.id}}
data-test-secret-list-tab="Configuration"
>Configuration</LinkTo></li>
</ul>
</nav>
</:tabs>
</Page::Header>
</Page::Header>
<nav class="tabs" aria-label="pki tabs">
<ul>
<li><LinkTo @route="overview" @model={{@backend.id}} data-test-secret-list-tab="Overview">Overview</LinkTo></li>
<li><LinkTo @route="roles" @model={{@backend.id}} data-test-secret-list-tab="Roles">Roles</LinkTo></li>
<li><LinkTo @route="issuers" @model={{@backend.id}} data-test-secret-list-tab="Issuers">Issuers</LinkTo></li>
<li><LinkTo @route="keys" @model={{@backend.id}} data-test-secret-list-tab="Keys">Keys</LinkTo></li>
<li><LinkTo
@route="certificates"
@model={{@backend.id}}
data-test-secret-list-tab="Certificates"
>Certificates</LinkTo></li>
<li><LinkTo @route="tidy" @model={{@backend.id}} data-test-secret-list-tab="Tidy">Tidy</LinkTo></li>
<li><LinkTo
@route="configuration"
@model={{@backend.id}}
data-test-secret-list-tab="Configuration"
>Configuration</LinkTo></li>
</ul>
</nav>

View file

@ -7,17 +7,16 @@
<:breadcrumbs>
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
</:breadcrumbs>
<:tabs>
<nav class="tabs" aria-label="secret tabs">
<ul>
{{#each this.tabs as |oTab|}}
<LinkTo @route={{oTab.route}} data-test-tab={{oTab.route}}>
{{oTab.label}}
</LinkTo>
{{/each}}
</ul>
</nav>
</:tabs>
</Page::Header>
<nav class="tabs" aria-label="secret tabs">
<ul>
{{#each this.tabs as |oTab|}}
<LinkTo @route={{oTab.route}} data-test-tab={{oTab.route}}>
{{oTab.label}}
</LinkTo>
{{/each}}
</ul>
</nav>
<Page::Error @error={{this.model}} />

View file

@ -49,7 +49,7 @@ module('Acceptance | auth backend list', function (hooks) {
await createUser(this.path1, this.user1);
// navigate back to the methods list
await click(SELECTORS.methods);
await click(GENERAL.breadcrumbAtIdx(0));
assert.strictEqual(currentURL(), '/vault/access');
// enable a second user in the second userpass backend
@ -59,7 +59,7 @@ module('Acceptance | auth backend list', function (hooks) {
assert.dom(SELECTORS.listItem).hasText(this.user2, 'user2 exists in the list');
// check that switching back to the first auth method shows the first user
await click(SELECTORS.methods);
await click(GENERAL.breadcrumbAtIdx(0));
await click(GENERAL.linkedBlock(this.path1));
assert.dom(SELECTORS.listItem).hasText(this.user1, 'user1 exists in the list');
@ -98,6 +98,7 @@ module('Acceptance | auth backend list', function (hooks) {
const itemSelector = `${GENERAL.linkedBlock(path)} .hds-dropdown-list-item`;
await click(triggerSelector);
assert
.dom(itemSelector)
.exists({ count: itemCount }, `shows ${itemCount} dropdown items for ${type}`);

View file

@ -8,6 +8,7 @@ import { visit, currentURL } from '@ember/test-helpers';
import { setupApplicationTest } from 'vault/tests/helpers';
import { login } from 'vault/tests/helpers/auth/auth-helpers';
import { DASHBOARD } from 'vault/tests/helpers/components/dashboard/dashboard-selectors';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
import Sinon from 'sinon';
module('Acceptance | landing page dashboard', function (hooks) {
@ -25,12 +26,12 @@ module('Acceptance | landing page dashboard', function (hooks) {
test('display the version number for the title', async function (assert) {
await login();
// Since we're using mirage, version is mocked static value
const versionText = this.version.isEnterprise
? `Vault ${this.version.versionDisplay} root`
: `Vault ${this.version.versionDisplay}`;
assert.dom(GENERAL.hdsPageHeaderTitle).hasText(`Vault ${this.version.versionDisplay}`);
});
assert.dom(DASHBOARD.cardHeader('Vault version')).hasText(versionText);
test('display the namespace badge for enterprise', async function (assert) {
await login();
assert.dom('.hds-badge').hasText('root', 'shows root namespace for enterprise');
});
test('hides the configuration details card on a non-root namespace enterprise version', async function (assert) {

View file

@ -52,7 +52,7 @@ module('Acceptance | mfa-login-enforcement', function (hooks) {
await click(GENERAL.tab('enforcements'));
await click('[data-test-enforcement-create]');
assert.dom('[data-test-mleh-title]').hasText('New enforcement', 'Title renders');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('New enforcement', 'Title renders');
await click('[data-test-mlef-save]');
assert
.dom('[data-test-inline-error-message]')

View file

@ -52,10 +52,8 @@ module('Acceptance | oidc auth method', function (hooks) {
triggerMessageEvent('oidc');
await click(GENERAL.submitButton);
await waitFor('[data-test-dashboard-card-header="Vault version"]');
assert
.dom('[data-test-dashboard-card-header="Vault version"]')
.exists('Render the dashboard landing page.');
await waitFor(GENERAL.hdsPageHeaderTitle);
assert.dom(GENERAL.hdsPageHeaderTitle).exists('Render the dashboard landing page.');
await logout();
assert.dom(AUTH_FORM.selectMethod).hasValue('oidc', 'Previous auth method selected on logout');

View file

@ -18,7 +18,6 @@ import { GENERAL } from 'vault/tests/helpers/general-selectors';
const { unsealKeys } = VAULT_KEYS;
const SELECTORS = {
footerVersion: `[data-test-footer-version]`,
dashboardTitle: `[data-test-dashboard-card-header="Vault version"]`,
};
module('Acceptance | reduced disclosure test', function (hooks) {
@ -39,7 +38,7 @@ module('Acceptance | reduced disclosure test', function (hooks) {
assert.strictEqual(currentURL(), '/vault/dashboard');
// Ensure it shows version on dashboard
assert.dom(SELECTORS.dashboardTitle).includesText(`Vault v1.`);
assert.dom(GENERAL.hdsPageHeaderTitle).includesText(`Vault v1.`);
assert
.dom(SELECTORS.footerVersion)
.hasText(`Vault ${this.versionSvc.version}`, 'shows Vault version after login');
@ -160,7 +159,7 @@ module('Acceptance | reduced disclosure test', function (hooks) {
`Vault ${this.versionSvc.version}`,
'shows Vault version for default policy in child namespace'
);
assert.dom(SELECTORS.dashboardTitle).includesText('Vault v1.');
assert.dom(GENERAL.hdsPageHeaderTitle).includesText('Vault v1.');
// log in to "root" before deleting
await login();
@ -174,7 +173,7 @@ module('Acceptance | reduced disclosure test', function (hooks) {
assert.strictEqual(currentURL(), '/vault/dashboard');
// Ensure it shows version on dashboard
assert.dom(SELECTORS.dashboardTitle).includesText(`Vault v1.`);
assert.dom(GENERAL.hdsPageHeaderTitle).includesText(`Vault v1.`);
assert
.dom(SELECTORS.footerVersion)
.hasText(`Vault ${this.versionSvc.version}`, 'shows Vault version after login');

View file

@ -63,7 +63,7 @@ module('Acceptance | reset password', function (hooks) {
'shows correct banner text'
);
assert.dom('[data-test-title]').hasText('Reset password', 'page title');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Reset password', 'page title');
await fillIn('[data-test-input="reset-password"]', 'newpassword');
await click(GENERAL.submitButton);
await waitFor('[data-test-flash-message]');

View file

@ -82,7 +82,7 @@ module('Acceptance | aws secret backend', function (hooks) {
);
await click(SES.createSecretLink);
assert.dom(SES.secretHeader).hasText('Create an AWS Role', 'It renders the create role page');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Create an AWS Role', 'It renders the create role page');
await fillIn(GENERAL.inputByAttr('name'), roleName);
await click(GENERAL.submitButton);

View file

@ -121,7 +121,9 @@ module('Acceptance | ssh | roles', function (hooks) {
for (const role of ROLES) {
// create a role
await click(SES.createSecretLink);
assert.dom(SES.secretHeader).includesText('SSH Role', `${role.type}: renders the create page`);
assert
.dom(GENERAL.hdsPageHeaderTitle)
.includesText('SSH Role', `${role.type}: renders the create page`);
await fillIn(GENERAL.inputByAttr('name'), role.name);
await fillIn(GENERAL.inputByAttr('keyType'), role.type);

View file

@ -74,7 +74,8 @@ module('Acceptance | totp key backend', function (hooks) {
await click(GENERAL.menuTrigger);
await click(`${GENERAL.menuItem('details')}`);
assert.dom('.title').hasText(`TOTP key ${this.keyName}`);
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('TOTP key');
assert.dom(GENERAL.hdsPageHeaderSubtitle).hasText(this.keyName);
assert.dom('[data-test-totp-key-details]').exists();
assert.strictEqual(
@ -101,7 +102,7 @@ module('Acceptance | totp key backend', function (hooks) {
test('it creates a key with Vault as the provider', async function (assert) {
await click(SES.createSecretLink);
assert.dom(SES.secretHeader).hasText('Create a TOTP key', 'It renders the create key page');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Create a TOTP key', 'It renders the create key page');
await createVaultKey(this.keyName, this.issuer, this.accountName);
assert.dom('[data-test-qrcode]').exists('QR code exists');
@ -121,7 +122,7 @@ module('Acceptance | totp key backend', function (hooks) {
test('it creates a key with another service as the provider with URL', async function (assert) {
await click(SES.createSecretLink);
assert.dom(SES.secretHeader).hasText('Create a TOTP key', 'It renders the create key page');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Create a TOTP key', 'It renders the create key page');
await createNonVaultKey(this.keyName, this.issuer, this.accountName, this.url);
await waitUntil(() => currentURL() === `/vault/secrets-engines/${this.path}/show/${this.keyName}`);
assert.strictEqual(
@ -136,7 +137,7 @@ module('Acceptance | totp key backend', function (hooks) {
test('it creates a key with another service as the provider with key', async function (assert) {
await click(SES.createSecretLink);
assert.dom(SES.secretHeader).hasText('Create a TOTP key', 'It renders the create key page');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Create a TOTP key', 'It renders the create key page');
await createNonVaultKey(this.keyName, this.issuer, this.accountName, undefined, this.key);
await waitUntil(() => currentURL() === `/vault/secrets-engines/${this.path}/show/${this.keyName}`);
assert.strictEqual(

View file

@ -10,6 +10,7 @@ import { hbs } from 'ember-cli-htmlbars';
import { setupMirage } from 'ember-cli-mirage/test-support';
import { DASHBOARD } from 'vault/tests/helpers/components/dashboard/dashboard-selectors';
import { SECRET_ENGINE_SELECTORS as SES } from 'vault/tests/helpers/secret-engine/secret-engine-selectors';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
module('Integration | Component | dashboard/overview', function (hooks) {
setupRenderingTest(hooks);
@ -81,7 +82,7 @@ module('Integration | Component | dashboard/overview', function (hooks) {
this.replication = null;
this.vaultConfiguration = null;
await this.renderComponent();
assert.dom(DASHBOARD.cardHeader('Vault version')).exists();
assert.dom(GENERAL.hdsPageHeaderTitle).exists();
assert.dom(DASHBOARD.cardName('secrets-engines')).exists();
assert.dom(DASHBOARD.emptyState('secrets-engines')).exists();
assert.dom(DASHBOARD.cardName('learn-more')).exists();
@ -115,7 +116,7 @@ module('Integration | Component | dashboard/overview', function (hooks) {
);
await this.renderComponent();
assert.dom(DASHBOARD.cardHeader('Vault version')).exists();
assert.dom(GENERAL.hdsPageHeaderTitle).exists();
assert.dom(DASHBOARD.cardName('secrets-engines')).exists();
assert.dom(DASHBOARD.cardName('learn-more')).exists();
assert.dom(DASHBOARD.cardName('quick-actions')).exists();
@ -149,7 +150,7 @@ module('Integration | Component | dashboard/overview', function (hooks) {
},
};
await this.renderComponent();
assert.dom(DASHBOARD.cardHeader('Vault version')).exists();
assert.dom(GENERAL.hdsPageHeaderTitle).exists();
assert.dom(DASHBOARD.cardName('secrets-engines')).exists();
assert.dom(DASHBOARD.cardName('learn-more')).exists();
assert.dom(DASHBOARD.cardName('quick-actions')).exists();

View file

@ -9,6 +9,7 @@ import EmberObject from '@ember/object';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
import timestamp from 'core/utils/timestamp';
module('Integration | Component | keymgmt/key-edit', function (hooks) {
@ -43,7 +44,7 @@ module('Integration | Component | keymgmt/key-edit', function (hooks) {
test('it renders show view as default', async function (assert) {
assert.expect(8);
await render(hbs`<Keymgmt::KeyEdit @model={{this.model}} @tab={{this.tab}} />`);
assert.dom('[data-test-secret-header]').hasText('Unicorns', 'Shows key name');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Unicorns', 'Shows key name');
assert.dom('[data-test-keymgmt-key-toolbar]').exists('Subnav toolbar exists');
assert.dom('[data-test-tab="Details"]').exists('Details tab exists');
assert.dom('[data-test-tab="Versions"]').exists('Versions tab exists');
@ -67,7 +68,7 @@ module('Integration | Component | keymgmt/key-edit', function (hooks) {
this.set('model', model);
await render(hbs`<Keymgmt::KeyEdit @model={{this.model}} @mode={{this.mode}} />`);
assert.dom('[data-test-secret-header]').hasText('Edit Key', 'Shows edit header');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Edit Key', 'Shows edit header');
assert.dom('[data-test-keymgmt-key-toolbar]').doesNotExist('Subnav toolbar does not exist');
assert.dom('[data-test-tab="Details"]').doesNotExist('Details tab does not exist');
assert.dom('[data-test-tab="Versions"]').doesNotExist('Versions tab does not exist');
@ -80,7 +81,7 @@ module('Integration | Component | keymgmt/key-edit', function (hooks) {
this.set('model', model);
await render(hbs`<Keymgmt::KeyEdit @model={{this.model}} @mode={{this.mode}} />`);
assert.dom('[data-test-secret-header]').hasText('Create Key', 'Shows edit header');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Create Key', 'Shows edit header');
assert.dom('[data-test-keymgmt-key-toolbar]').doesNotExist('Subnav toolbar does not exist');
assert.dom('[data-test-tab="Details"]').doesNotExist('Details tab does not exist');
assert.dom('[data-test-tab="Versions"]').doesNotExist('Versions tab does not exist');

View file

@ -58,7 +58,7 @@ module('Integration | Component | keymgmt/provider-edit', function (hooks) {
});
test('it should render show view', async function (assert) {
assert.expect(10);
assert.expect(11);
// override capability getters
Object.defineProperties(this.model, {
@ -88,7 +88,8 @@ module('Integration | Component | keymgmt/provider-edit', function (hooks) {
@tab={{this.tab}}
/>`);
assert.dom(`[${ts}-header]`).hasText('Provider foo-bar', 'Page header renders');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Provider', 'Page header renders');
assert.dom(GENERAL.hdsPageHeaderSubtitle).hasText(' foo-bar', 'Page header renders subtitle');
assert.dom(`[${ts}-tab="details"]`).hasClass('active', 'Details tab is active');
const infoRows = this.element.querySelectorAll('[data-test-component="info-table-row"]');
@ -194,7 +195,7 @@ module('Integration | Component | keymgmt/provider-edit', function (hooks) {
@mode="create"
/>`);
assert.dom(`[${ts}-header]`).hasText('Create Provider', 'Page header renders');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Create Provider', 'Page header renders');
assert.dom(`[${ts}-config-title]`).exists('Config header shown in create mode');
assert.dom(`[${ts}-creds-title]`).doesNotExist('New credentials header hidden in create mode');
@ -256,7 +257,7 @@ module('Integration | Component | keymgmt/provider-edit', function (hooks) {
@mode="edit"
/>`);
assert.dom(`[${ts}-header]`).hasText('Update Credentials', 'Page header renders');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Update Credentials', 'Page header renders');
assert.dom(`[${ts}-config-title]`).doesNotExist('Config header hidden in edit mode');
assert.dom(`[${ts}-creds-title]`).exists('New credentials header shown in edit mode');

View file

@ -10,6 +10,7 @@ import { hbs } from 'ember-cli-htmlbars';
import { setupMirage } from 'ember-cli-mirage/test-support';
import { clickTrigger } from 'ember-power-select/test-support/helpers';
import { setRunOptions } from 'ember-a11y-testing/test-support';
import { GENERAL } from 'vault/tests/helpers/general-selectors';
module('Integration | Component | mfa-login-enforcement-header', function (hooks) {
setupRenderingTest(hooks);
@ -31,10 +32,10 @@ module('Integration | Component | mfa-login-enforcement-header', function (hooks
test('it renders heading', async function (assert) {
await render(hbs`<Mfa::MfaLoginEnforcementHeader @heading="New enforcement" />`);
assert.dom('[data-test-mleh-title]').includesText('New enforcement');
assert.dom('[data-test-mleh-title] svg').hasClass('hds-icon-lock', 'Lock icon renders');
assert.dom(GENERAL.hdsPageHeaderTitle).includesText('New enforcement');
assert.dom(GENERAL.icon('lock')).hasClass('hds-icon-lock', 'Lock icon renders');
assert
.dom('[data-test-mleh-description]')
.dom(GENERAL.hdsPageHeaderDescription)
.includesText('An enforcement will define which auth types', 'Description renders');
assert.dom('[data-test-mleh-radio]').doesNotExist('Radio cards are hidden when not inline display mode');
assert
@ -66,9 +67,9 @@ module('Integration | Component | mfa-login-enforcement-header', function (hooks
/>
`);
assert.dom('[data-test-mleh-title]').includesText('Enforcement');
assert.dom(GENERAL.hdsPageHeaderTitle).includesText('Enforcement');
assert
.dom('[data-test-mleh-description]')
.dom(GENERAL.hdsPageHeaderDescription)
.includesText('An enforcement includes the authentication types', 'Description renders');
for (const option of ['new', 'existing', 'skip']) {
await click(`[data-test-mleh-radio="${option}"] input`);

View file

@ -44,7 +44,7 @@ module('Integration | Component | mount backend form', function (hooks) {
hbs`<MountBackendForm @mountModel={{this.model}} @onMountSuccess={{this.onMountSuccess}} />`
);
assert
.dom(GENERAL.title)
.dom(GENERAL.hdsPageHeaderTitle)
.hasText('Enable an Authentication Method', 'renders auth header in default state');
for (const method of filterEnginesByMountCategory({

View file

@ -83,9 +83,7 @@ module('Integration | Component | oidc/client-form', function (hooks) {
/>
`);
await click(GENERAL.button('More options'));
assert
.dom('[data-test-oidc-client-title]')
.hasText('Create Application', 'Form title renders correct text');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Create Application', 'Form title renders correct text');
assert.dom(SELECTORS.clientSaveButton).hasText('Create', 'Save button has correct text');
assert.strictEqual(findAll('[data-test-field]').length, 6, 'renders all attribute fields');
assert
@ -150,7 +148,7 @@ module('Integration | Component | oidc/client-form', function (hooks) {
/>
`);
await click(GENERAL.button('More options'));
assert.dom('[data-test-oidc-client-title]').hasText('Edit Application', 'Title renders correct text');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Edit Application', 'Title renders correct text');
assert.dom(SELECTORS.clientSaveButton).hasText('Update', 'Save button has correct text');
assert.dom('[data-test-input="name"]').isDisabled('Name input is disabled when editing');
assert.dom('[data-test-input="name"]').hasValue('test-app', 'Name input is populated with model value');

View file

@ -67,9 +67,7 @@ module('Integration | Component | oidc/provider-form', function (hooks) {
/>
`);
assert
.dom('[data-test-oidc-provider-title]')
.hasText('Create Provider', 'Form title renders correct text');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Create Provider', 'Form title renders correct text');
assert.dom(SELECTORS.providerSaveButton).hasText('Create', 'Save button has correct text');
assert
.dom('[data-test-input="issuer"]')
@ -133,7 +131,7 @@ module('Integration | Component | oidc/provider-form', function (hooks) {
/>
`);
assert.dom('[data-test-oidc-provider-title]').hasText('Edit Provider', 'Title renders correct text');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Edit Provider', 'Title renders correct text');
assert.dom(SELECTORS.providerSaveButton).hasText('Update', 'Save button has correct text');
assert.dom('[data-test-input="name"]').isDisabled('Name input is disabled when editing');
assert

View file

@ -39,7 +39,7 @@ module('Integration | Component | oidc/scope-form', function (hooks) {
/>
`);
assert.dom('[data-test-oidc-scope-title]').hasText('Create Scope', 'Form title renders');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Create Scope', 'Form title renders');
assert.dom(SELECTORS.scopeSaveButton).hasText('Create', 'Save button has correct label');
await click(SELECTORS.scopeSaveButton);
@ -88,7 +88,7 @@ module('Integration | Component | oidc/scope-form', function (hooks) {
/>
`);
assert.dom('[data-test-oidc-scope-title]').hasText('Edit Scope', 'Form title renders');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Edit Scope', 'Form title renders');
assert.dom(SELECTORS.scopeSaveButton).hasText('Update', 'Save button has correct label');
assert.dom(GENERAL.inputByAttr('name')).isDisabled('Name input is disabled when editing');
assert.dom(GENERAL.inputByAttr('name')).hasValue('test', 'Name input is populated with model value');

View file

@ -52,7 +52,7 @@ module('Integration | Component | totp/key-form', function (hooks) {
/>
`);
assert.dom('[data-test-secret-header]').hasText('Create a TOTP key', 'Form title renders');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Create a TOTP key', 'Form title renders');
// check validation errors
await click(GENERAL.submitButton);
@ -110,7 +110,7 @@ module('Integration | Component | totp/key-form', function (hooks) {
/>
`);
assert.dom('[data-test-secret-header]').hasText('Create a TOTP key', 'Form title renders');
assert.dom(GENERAL.hdsPageHeaderTitle).hasText('Create a TOTP key', 'Form title renders');
// switch to non-generated form fields
await click(GENERAL.radioByAttr('Other service'));