From 22e6ce0df10091bc66ee7fbf8e5d1c0f158ab5a9 Mon Sep 17 00:00:00 2001 From: Chris Hut Date: Thu, 1 Feb 2024 15:04:01 -0800 Subject: [PATCH] Add nav bar item to show HCP link status and encourage folks to link (#20370) * Convert consul-hcp to a simpler component * update existing test to use envStub helper * An hcp link item for the navbar * A method of linking to HCP * Hook up fetching linking status to the nav-item * Hooking up fetching link status to the hcp link friend * Adding some tests * remove a comment - but also fix padding justify-content * Fix the banner tests * Adding permission tests as well * some more sane formatting * Rename function with its now multipurpose use * Feature change: No more NEW Badge since it breaks padding - instead a linked badge * Removing unused class --- .../consul-ui/app/abilities/operator.js | 10 + .../app/components/hashicorp-consul/index.hbs | 4 +- .../app/components/hcp-nav-item/index.hbs | 19 ++ .../app/components/hcp-nav-item/index.js | 35 +++ .../app/helpers/hcp-resource-id-to-link.js | 32 +++ .../consul-ui/app/services/hcp-link-status.js | 7 +- .../app/services/repository/hcp-link.js | 48 +++- .../consul-ui/mock-api/api/hcp/v2/link/global | 31 ++- ...hcp-banner-test.js => link-to-hcp-test.js} | 14 +- .../components/hcp-nav-item-test.js | 255 ++++++++++++++---- .../helpers/hcp-resource-id-to-link-test.js | 41 +++ .../consul-ui/tests/unit/abilities/-test.js | 3 +- 12 files changed, 427 insertions(+), 72 deletions(-) create mode 100644 ui/packages/consul-ui/app/abilities/operator.js create mode 100644 ui/packages/consul-ui/app/helpers/hcp-resource-id-to-link.js rename ui/packages/consul-ui/tests/acceptance/{link-to-hcp-banner-test.js => link-to-hcp-test.js} (68%) create mode 100644 ui/packages/consul-ui/tests/integration/helpers/hcp-resource-id-to-link-test.js 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 0000000000..4cec68fad7 --- /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 fc508b17c6..b7311b3143 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 487984511e..005d32f4b9 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 0000000000..25ed105bca --- /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 cdde716ee4..47b5de0ec0 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 f82296cd09..4f44f60ec9 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 873f854c20..e4274f1c52 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 4761634d3d..3d43490d00 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 8fc7bfa975..32c784baf7 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, - }; - } - ); + 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` + 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` + + + + `); + + 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(backToHcpSelector).doesNotExist(); + assert.dom('a').doesNotExist(); + }); }); - 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, - }; - } - ); + module('when rendered in self managed mode', function (hooks) { + hooks.beforeEach(function () { + this.owner.register( + 'service:env', + class Stub extends EnvStub { + stubEnv = {}; + } + ); + }); - await render(hbs` - - - - `); + 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'); + }); - 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, - }; - } - ); + 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'); + }); - await render(hbs` - - - - `); + 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'); + }); - assert.dom('[data-test-back-to-hcp]').doesNotExist(); - assert.dom('a').doesNotExist(); + 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 0000000000..366186f853 --- /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 f64d514a61..0a7a9e0bd5 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)