diff --git a/ui/packages/consul-ui/app/abilities/operator.js b/ui/packages/consul-ui/app/abilities/operator.js
new file mode 100644
index 000000000000..4cec68fad7d4
--- /dev/null
+++ b/ui/packages/consul-ui/app/abilities/operator.js
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import BaseAbility from './base';
+
+export default class OperatorAbility extends BaseAbility {
+ resource = 'operator';
+}
diff --git a/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs b/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs
index fc508b17c6b5..b7311b3143c9 100644
--- a/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs
+++ b/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs
@@ -122,7 +122,9 @@
class='hds-side-nav-hide-when-minimized consul-side-nav__selector-group'
as |SNL|
>
-
+
+
+
+ {{else}}
+ {{#if this.shouldDisplayNavLinkItem}}
+ {{#if this.alreadyLinked}}
+
+ {{else}}
+
+
+
+ {{/if}}
+ {{/if}}
{{/if}}
{{/let}}
\ No newline at end of file
diff --git a/ui/packages/consul-ui/app/components/hcp-nav-item/index.js b/ui/packages/consul-ui/app/components/hcp-nav-item/index.js
index 487984511ed2..005d32f4b9d9 100644
--- a/ui/packages/consul-ui/app/components/hcp-nav-item/index.js
+++ b/ui/packages/consul-ui/app/components/hcp-nav-item/index.js
@@ -5,6 +5,7 @@
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
+import { action } from '@ember/object';
/**
* If the user has accessed consul from HCP managed consul, we do NOT want to display the
@@ -12,10 +13,44 @@ import { inject as service } from '@ember/service';
*/
export default class HcpLinkItemComponent extends Component {
@service env;
+ @service('hcp-link-status') hcpLinkStatus;
+
+ get alreadyLinked() {
+ return this.args.linkData?.isLinked;
+ }
+
+ get shouldDisplayNavLinkItem() {
+ const alreadyLinked = this.alreadyLinked;
+ const undefinedResourceId = !this.args.linkData?.resourceId;
+ const unauthorizedToLink = !this.hcpLinkStatus.hasPermissionToLink;
+ const undefinedLinkStatus = this.args.linkData?.isLinked === undefined;
+
+ // We need permission to link to display the link nav item
+ if (unauthorizedToLink) {
+ return false;
+ }
+
+ // If the link status is undefined, we don't want to display the link nav item
+ if (undefinedLinkStatus) {
+ return false;
+ }
+
+ // If the user has already linked, but we don't have the resourceId to link them to HCP, we don't want to display the link nav item
+ if (alreadyLinked && undefinedResourceId) {
+ return false;
+ }
+
+ return true;
+ }
get shouldShowBackToHcpItem() {
const isConsulHcpUrlDefined = !!this.env.var('CONSUL_HCP_URL');
const isConsulHcpEnabled = !!this.env.var('CONSUL_HCP_ENABLED');
return isConsulHcpEnabled && isConsulHcpUrlDefined;
}
+
+ @action
+ onLinkToConsulCentral() {
+ // TODO: https://hashicorp.atlassian.net/browse/CC-7147 open the modal
+ }
}
diff --git a/ui/packages/consul-ui/app/helpers/hcp-resource-id-to-link.js b/ui/packages/consul-ui/app/helpers/hcp-resource-id-to-link.js
new file mode 100644
index 000000000000..25ed105bcacc
--- /dev/null
+++ b/ui/packages/consul-ui/app/helpers/hcp-resource-id-to-link.js
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import Helper from '@ember/component/helper';
+
+/**
+ * A resourceId Looks like:
+ * organization/b4432207-bb9c-438e-a160-b98923efa979/project/4b09958c-fa91-43ab-8029-eb28d8cee9d4/hashicorp.consul.global-network-manager.cluster/test-from-api
+ * organization/${organizationId}/project/${projectId}/hashicorp.consul.global-network-manager.cluster/${clusterName}
+ *
+ * A HCP URL looks like:
+ * https://portal.hcp.dev/services/consul/clusters/self-managed/test-from-api?project_id=4b09958c-fa91-43ab-8029-eb28d8cee9d4
+ * ${HCP_PREFIX}/${clusterName}?project_id=${projectId}
+ */
+export const HCP_PREFIX =
+ 'https://portal.cloud.hashicorp.com/services/consul/clusters/self-managed';
+export default class hcpResourceIdToLink extends Helper {
+ // TODO: How can we figure out different HCP environments?
+ compute([resourceId], hash) {
+ let url = HCP_PREFIX;
+ // Array looks like: ["organization", organizationId, "project", projectId, "hashicorp.consul.global-network-manager.cluster", "Cluster Id"]
+ const [, , , projectId, , clusterName] = resourceId.split('/');
+ if (!projectId || !clusterName) {
+ return '';
+ }
+
+ url += `/${clusterName}?project_id=${projectId}`;
+ return url;
+ }
+}
diff --git a/ui/packages/consul-ui/app/services/hcp-link-status.js b/ui/packages/consul-ui/app/services/hcp-link-status.js
index cdde716ee4ea..47b5de0ec0c2 100644
--- a/ui/packages/consul-ui/app/services/hcp-link-status.js
+++ b/ui/packages/consul-ui/app/services/hcp-link-status.js
@@ -10,12 +10,17 @@ const LOCAL_STORAGE_KEY = 'consul:hideHcpLinkBanner';
export default class HcpLinkStatus extends Service {
@service('env') env;
+ @service abilities;
@tracked
userDismissedBanner = false;
get shouldDisplayBanner() {
const hcpLinkEnabled = this.env.var('CONSUL_HCP_LINK_ENABLED');
- return !this.userDismissedBanner && hcpLinkEnabled;
+ return !this.userDismissedBanner && this.hasPermissionToLink && hcpLinkEnabled;
+ }
+
+ get hasPermissionToLink() {
+ return this.abilities.can('write operators') && this.abilities.can('write acls');
}
constructor() {
diff --git a/ui/packages/consul-ui/app/services/repository/hcp-link.js b/ui/packages/consul-ui/app/services/repository/hcp-link.js
index f82296cd0985..4f44f60ec900 100644
--- a/ui/packages/consul-ui/app/services/repository/hcp-link.js
+++ b/ui/packages/consul-ui/app/services/repository/hcp-link.js
@@ -7,6 +7,44 @@ import RepositoryService from 'consul-ui/services/repository';
import dataSource from 'consul-ui/decorators/data-source';
export default class HcpLinkService extends RepositoryService {
+ /**
+ * Data looks like
+ * {
+ * "data": {
+ * "clientId": "5wZyAPvDFbgDdO3439m8tufwO9hElphu",
+ * "clientSecret": "SWX0XShcp3doc7RF8YCjJ-WATyeMAjFaf1eA0mnzlNHLF4IXbFz6xyjSZvHzAR_i",
+ * "resourceId": "organization/b4432207-bb9c-438e-a160-b98923efa979/project/4b09958c-fa91-43ab-8029-eb28d8cee9d4/hashicorp.consul.global-network-manager.cluster/test-from-api"
+ * },
+ * "generation": "01HMSDHXQTCQGD3Z68B3H58YFE",
+ * "id": {
+ * "name": "global",
+ * "tenancy": {
+ * "peerName": "local"
+ * },
+ * "type": {
+ * "group": "hcp",
+ * "groupVersion": "v2",
+ * "kind": "Link"
+ * },
+ * "uid": "01HMSDHXQTCQGD3Z68B10WBWHX"
+ * },
+ * "status": {
+ * "consul.io/hcp/link": {
+ * "conditions": [
+ * {
+ * "message": "Failed to link to HCP",
+ * "reason": "FAILED",
+ * "state": "STATE_FALSE",
+ * "type": "linked"
+ * }
+ * ],
+ * "observedGeneration": "01HMSDHXQTCQGD3Z68B3H58YFE",
+ * "updatedAt": "2024-01-22T20:24:57.141144170Z"
+ * }
+ * },
+ * "version": "57"
+ * }
+ */
@dataSource('/:partition/:ns/:dc/hcp-link')
async fetch({ partition, ns, dc }, { uri }, request) {
let result;
@@ -16,15 +54,19 @@ export default class HcpLinkService extends RepositoryService {
GET /api/hcp/v2/link/global
`
)((headers, body) => {
+ const isLinked = (body.status['consul.io/hcp/link']['conditions'] || []).some(
+ (condition) => condition.type === 'linked' && condition.state === 'STATE_TRUE'
+ );
+ const resourceId = body.data?.resourceId;
+
return {
meta: {
version: 2,
uri: uri,
},
body: {
- isLinked: (body.status['consul.io/hcp/link']['conditions'] || []).some(
- (condition) => condition.type === 'linked' && condition.state === 'STATE_TRUE'
- ),
+ isLinked,
+ resourceId,
},
headers,
};
diff --git a/ui/packages/consul-ui/mock-api/api/hcp/v2/link/global b/ui/packages/consul-ui/mock-api/api/hcp/v2/link/global
index 873f854c202d..e4274f1c5294 100644
--- a/ui/packages/consul-ui/mock-api/api/hcp/v2/link/global
+++ b/ui/packages/consul-ui/mock-api/api/hcp/v2/link/global
@@ -1,16 +1,21 @@
{
- "status": {
- "consul.io/hcp/link": {
- "conditions": [
- {
- "message": "Successfully linked to cluster 'organization/f53e5646-6529-4698-ae29-d74f8bd22a01/project/6994bb7a-5561-4d5c-8bb0-cf40177e5b77/hashicorp.consul.global-network-manager.cluster/mkam-vm'",
- "reason": "SUCCESS",
- "state": "STATE_FALSE",
- "type": "linked"
- }
- ],
- "observedGeneration":"01HMA2VPHVKNF6QR8TD07KDN5K",
- "updatedAt":"2024-01-16T21:29:25.923140Z"
- }
+ "data": {
+ "clientId": "5wZyAPvDFbgDdO3439m8tufwO9hElphu",
+ "clientSecret": "SWX0XShcp3doc7RF8YCjJ-WATyeMAjFaf1eA0mnzlNHLF4IXbFz6xyjSZvHzAR_i",
+ "resourceId": "organization/b4432207-bb9c-438e-a160-b98923efa979/project/4b09958c-fa91-43ab-8029-eb28d8cee9d4/hashicorp.consul.global-network-manager.cluster/test-from-api"
+ },
+ "status": {
+ "consul.io/hcp/link": {
+ "conditions": [
+ {
+ "message": "Successfully linked to cluster 'organization/f53e5646-6529-4698-ae29-d74f8bd22a01/project/6994bb7a-5561-4d5c-8bb0-cf40177e5b77/hashicorp.consul.global-network-manager.cluster/mkam-vm'",
+ "reason": "SUCCESS",
+ "state": "STATE_FALSE",
+ "type": "linked"
+ }
+ ],
+ "observedGeneration":"01HMA2VPHVKNF6QR8TD07KDN5K",
+ "updatedAt":"2024-01-16T21:29:25.923140Z"
}
+ }
}
\ No newline at end of file
diff --git a/ui/packages/consul-ui/tests/acceptance/link-to-hcp-banner-test.js b/ui/packages/consul-ui/tests/acceptance/link-to-hcp-test.js
similarity index 68%
rename from ui/packages/consul-ui/tests/acceptance/link-to-hcp-banner-test.js
rename to ui/packages/consul-ui/tests/acceptance/link-to-hcp-test.js
index 4761634d3d37..3d43490d0042 100644
--- a/ui/packages/consul-ui/tests/acceptance/link-to-hcp-banner-test.js
+++ b/ui/packages/consul-ui/tests/acceptance/link-to-hcp-test.js
@@ -9,7 +9,8 @@ import { setupApplicationTest } from 'ember-qunit';
import { EnvStub } from 'consul-ui/services/env';
const bannerSelector = '[data-test-link-to-hcp-banner]';
-module('Acceptance | link to hcp banner', function (hooks) {
+const linkToHcpSelector = '[data-test-link-to-hcp]';
+module('Acceptance | link to hcp', function (hooks) {
setupApplicationTest(hooks);
hooks.beforeEach(function () {
@@ -25,18 +26,23 @@ module('Acceptance | link to hcp banner', function (hooks) {
);
});
- test('the banner is initially displayed on services page', async function (assert) {
- assert.expect(3);
+ test('the banner and nav item are initially displayed on services page', async function (assert) {
// default route is services page so we're good here
await visit('/');
// Expect the banner to be visible by default
- assert.dom(bannerSelector).exists({ count: 1 });
+ assert.dom(bannerSelector).isVisible('Banner is visible by default');
+ // expect linkToHCP nav item to be visible as well
+ assert.dom(linkToHcpSelector).isVisible('Link to HCP nav item is visible by default');
// Click on the dismiss button
await click(`${bannerSelector} button[aria-label="Dismiss"]`);
assert.dom(bannerSelector).doesNotExist('Banner is gone after dismissing');
+ // link to HCP nav item still there
+ assert.dom(linkToHcpSelector).isVisible('Link to HCP nav item is visible by default');
// Refresh the page
await visit('/');
assert.dom(bannerSelector).doesNotExist('Banner is still gone after refresh');
+ // link to HCP nav item still there
+ assert.dom(linkToHcpSelector).isVisible('Link to HCP nav item is visible by default');
});
test('the banner is not displayed if the env var is not set', async function (assert) {
diff --git a/ui/packages/consul-ui/tests/integration/components/hcp-nav-item-test.js b/ui/packages/consul-ui/tests/integration/components/hcp-nav-item-test.js
index 8fc7bfa97507..32c784baf7ce 100644
--- a/ui/packages/consul-ui/tests/integration/components/hcp-nav-item-test.js
+++ b/ui/packages/consul-ui/tests/integration/components/hcp-nav-item-test.js
@@ -8,69 +8,228 @@ import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import { EnvStub } from 'consul-ui/services/env';
+import Service from '@ember/service';
+const backToHcpSelector = '[data-test-back-to-hcp]';
+const hcpConsulCentralItemSelector = '[data-test-linked-cluster-hcp-link]';
+const linkToHcpSelector = '[data-test-link-to-hcp]';
+const resourceId =
+ 'organization/b4432207-bb9c-438e-a160-b98923efa979/project/4b09958c-fa91-43ab-8029-eb28d8cee9d4/hashicorp.consul.global-network-manager.cluster/test-from-api';
module('Integration | Component | hcp nav item', function (hooks) {
setupRenderingTest(hooks);
- test('it prints the value of CONSUL_HCP_URL', async function (assert) {
- this.owner.register(
- 'service:env',
- class Stub extends EnvStub {
- stubEnv = {
- CONSUL_HCP_URL: 'http://hcp.com',
- CONSUL_HCP_ENABLED: true,
- };
- }
- );
-
- await render(hbs`
+ module('back to hcp item', function () {
+ test('it prints the value of CONSUL_HCP_URL when env vars are set', async function (assert) {
+ this.owner.register(
+ 'service:env',
+ class Stub extends EnvStub {
+ stubEnv = {
+ CONSUL_HCP_URL: 'http://hcp.com',
+ CONSUL_HCP_ENABLED: true,
+ };
+ }
+ );
+
+ await render(hbs`
`);
- assert.dom('[data-test-back-to-hcp]').isVisible();
- assert.dom('a').hasAttribute('href', 'http://hcp.com');
- });
+ assert.dom(backToHcpSelector).isVisible();
+ assert.dom('a').hasAttribute('href', 'http://hcp.com');
+ assert.dom(linkToHcpSelector).doesNotExist('link to hcp should not be visible');
+ assert
+ .dom(hcpConsulCentralItemSelector)
+ .doesNotExist('hcp consul central item should not be visible');
+ });
- test('it does not output the Back to HCP link if CONSUL_HCP_URL is not present', async function (assert) {
- this.owner.register(
- 'service:env',
- class Stub extends EnvStub {
- stubEnv = {
- CONSUL_HCP_ENABLED: true,
- CONSUL_HCP_URL: undefined,
- };
- }
- );
-
- await render(hbs`
+ test('it does not output the Back to HCP link if CONSUL_HCP_URL is not present', async function (assert) {
+ this.owner.register(
+ 'service:env',
+ class Stub extends EnvStub {
+ stubEnv = {
+ CONSUL_HCP_ENABLED: true,
+ CONSUL_HCP_URL: undefined,
+ };
+ }
+ );
+
+ await render(hbs`
`);
- assert.dom('[data-test-back-to-hcp]').doesNotExist();
- assert.dom('a').doesNotExist();
- });
- test('it does not output the Back to HCP link if CONSUL_HCP_ENABLED is not present', async function (assert) {
- this.owner.register(
- 'service:env',
- class Stub extends EnvStub {
- stubEnv = {
- CONSUL_HCP_URL: 'http://hcp.com',
- CONSUL_HCP_ENABLED: undefined,
- };
- }
- );
-
- await render(hbs`
+ assert.dom(backToHcpSelector).doesNotExist();
+ assert.dom('a').doesNotExist();
+ });
+ test('it does not output the Back to HCP link if CONSUL_HCP_ENABLED is not present', async function (assert) {
+ this.owner.register(
+ 'service:env',
+ class Stub extends EnvStub {
+ stubEnv = {
+ CONSUL_HCP_URL: 'http://hcp.com',
+ CONSUL_HCP_ENABLED: undefined,
+ };
+ }
+ );
+
+ await render(hbs`
`);
- assert.dom('[data-test-back-to-hcp]').doesNotExist();
- assert.dom('a').doesNotExist();
+ assert.dom(backToHcpSelector).doesNotExist();
+ assert.dom('a').doesNotExist();
+ });
+ });
+
+ module('when rendered in self managed mode', function (hooks) {
+ hooks.beforeEach(function () {
+ this.owner.register(
+ 'service:env',
+ class Stub extends EnvStub {
+ stubEnv = {};
+ }
+ );
+ });
+
+ test('when unauthorized to link it does not display any nav items', async function (assert) {
+ this.owner.register(
+ 'service:hcp-link-status',
+ class Stub extends Service {
+ hasPermissionToLink = false;
+ }
+ );
+ this.linkData = {
+ resourceId,
+ isLinked: false,
+ };
+ await render(hbs`
+
+
+
+ `);
+ assert.dom(backToHcpSelector).doesNotExist('back to hcp should not be visible');
+ assert.dom(linkToHcpSelector).doesNotExist('link to hcp should not be visible');
+ assert
+ .dom(hcpConsulCentralItemSelector)
+ .doesNotExist('hcp consul central item should not be visible');
+ });
+
+ test('when link status is undefined it does not display any nav items', async function (assert) {
+ this.owner.register(
+ 'service:hcp-link-status',
+ class Stub extends Service {
+ hasPermissionToLink = true;
+ }
+ );
+ this.linkData = {
+ resourceId,
+ };
+ await render(hbs`
+
+
+
+ `);
+ assert.dom(backToHcpSelector).doesNotExist('back to hcp should not be visible');
+ assert.dom(linkToHcpSelector).doesNotExist('link to hcp should not be visible');
+ assert
+ .dom(hcpConsulCentralItemSelector)
+ .doesNotExist('hcp consul central item should not be visible');
+ });
+
+ test('when already linked but no resourceId it does not display any nav items', async function (assert) {
+ this.owner.register(
+ 'service:hcp-link-status',
+ class Stub extends Service {
+ hasPermissionToLink = true;
+ }
+ );
+ this.linkData = {
+ isLinked: true,
+ };
+ await render(hbs`
+
+
+
+ `);
+ assert.dom(backToHcpSelector).doesNotExist('back to hcp should not be visible');
+ assert.dom(linkToHcpSelector).doesNotExist('link to hcp should not be visible');
+ assert
+ .dom(hcpConsulCentralItemSelector)
+ .doesNotExist('hcp consul central item should not be visible');
+ });
+
+ test('when already linked and we have a resourceId it displays the link to hcp consul central item', async function (assert) {
+ this.owner.register(
+ 'service:hcp-link-status',
+ class Stub extends Service {
+ hasPermissionToLink = true;
+ }
+ );
+ this.linkData = {
+ isLinked: true,
+ resourceId,
+ };
+ await render(hbs`
+
+
+
+ `);
+ assert.dom(backToHcpSelector).doesNotExist('back to hcp should not be visible');
+ assert.dom(linkToHcpSelector).doesNotExist('link to hcp should not be visible');
+ assert
+ .dom(hcpConsulCentralItemSelector)
+ .isVisible('hcp consul central item should be visible');
+ });
+
+ test('when not already linked without dismissed banner it displays the link to hcp item', async function (assert) {
+ this.owner.register(
+ 'service:hcp-link-status',
+ class Stub extends Service {
+ hasPermissionToLink = true;
+ shouldDisplayBanner = true;
+ }
+ );
+ this.linkData = {
+ isLinked: false,
+ };
+ await render(hbs`
+
+
+
+ `);
+ assert.dom(backToHcpSelector).doesNotExist('back to hcp should not be visible');
+ assert
+ .dom(hcpConsulCentralItemSelector)
+ .doesNotExist('hcp consul central item should not be visible');
+ assert.dom(linkToHcpSelector).isVisible('link to hcp should be visible');
+ });
+
+ test('when not already linked with dismissed banner it displays the link to hcp item', async function (assert) {
+ this.owner.register(
+ 'service:hcp-link-status',
+ class Stub extends Service {
+ hasPermissionToLink = true;
+ shouldDisplayBanner = false;
+ }
+ );
+ this.linkData = {
+ isLinked: false,
+ };
+ await render(hbs`
+
+
+
+ `);
+ assert.dom(backToHcpSelector).doesNotExist('back to hcp should not be visible');
+ assert
+ .dom(hcpConsulCentralItemSelector)
+ .doesNotExist('hcp consul central item should not be visible');
+ assert.dom(linkToHcpSelector).isVisible('link to hcp should be visible');
+ });
});
});
diff --git a/ui/packages/consul-ui/tests/integration/helpers/hcp-resource-id-to-link-test.js b/ui/packages/consul-ui/tests/integration/helpers/hcp-resource-id-to-link-test.js
new file mode 100644
index 000000000000..366186f85397
--- /dev/null
+++ b/ui/packages/consul-ui/tests/integration/helpers/hcp-resource-id-to-link-test.js
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import { module, test } from 'qunit';
+import { render } from '@ember/test-helpers';
+import hbs from 'htmlbars-inline-precompile';
+import { setupRenderingTest } from 'ember-qunit';
+import { HCP_PREFIX } from 'consul-ui/helpers/hcp-resource-id-to-link';
+
+// organization/b4432207-bb9c-438e-a160-b98923efa979/project/4b09958c-fa91-43ab-8029-eb28d8cee9d4/hashicorp.consul.global-network-manager.cluster/test-from-api
+const clusterName = 'hello';
+const projectId = '4b09958c-fa91-43ab-8029-eb28d8cee9d4';
+const realResourceId = `organization/b4432207-bb9c-438e-a160-b98923efa979/project/${projectId}/hashicorp.consul.global-network-manager.cluster/${clusterName}`;
+module('Integration | Helper | hcp-resource-id-to-link', function (hooks) {
+ setupRenderingTest(hooks);
+ test('it makes a URL out of a real resourceId', async function (assert) {
+ this.resourceId = realResourceId;
+
+ await render(hbs`{{hcp-resource-id-to-link resourceId}}`);
+
+ assert.equal(
+ this.element.textContent.trim(),
+ `${HCP_PREFIX}/${clusterName}?project_id=${projectId}`
+ );
+ });
+
+ test('it returns empty string with invalid resourceId', async function (assert) {
+ this.resourceId = 'invalid';
+
+ await render(hbs`{{hcp-resource-id-to-link resourceId}}`);
+ assert.equal(this.element.textContent.trim(), '');
+
+ // not enough items in id
+ this.resourceId =
+ '`organization/b4432207-bb9c-438e-a160-b98923efa979/project/${projectId}/hashicorp.consul.global-network-manager.cluster`';
+ await render(hbs`{{hcp-resource-id-to-link resourceId}}`);
+ assert.equal(this.element.textContent.trim(), '');
+ });
+});
diff --git a/ui/packages/consul-ui/tests/unit/abilities/-test.js b/ui/packages/consul-ui/tests/unit/abilities/-test.js
index f64d514a61d4..0a7a9e0bd529 100644
--- a/ui/packages/consul-ui/tests/unit/abilities/-test.js
+++ b/ui/packages/consul-ui/tests/unit/abilities/-test.js
@@ -10,9 +10,8 @@ import { setupTest } from 'ember-qunit';
module('Unit | Ability | *', function (hooks) {
setupTest(hooks);
- // Replace this with your real tests.
test('it exists', function (assert) {
- assert.expect(228);
+ assert.expect(240);
const abilities = Object.keys(requirejs.entries)
.filter((key) => key.indexOf('/abilities/') !== -1)