mirror of https://github.com/status-im/consul.git
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
This commit is contained in:
parent
49025105f0
commit
22e6ce0df1
|
@ -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';
|
||||||
|
}
|
|
@ -122,7 +122,9 @@
|
||||||
class='hds-side-nav-hide-when-minimized consul-side-nav__selector-group'
|
class='hds-side-nav-hide-when-minimized consul-side-nav__selector-group'
|
||||||
as |SNL|
|
as |SNL|
|
||||||
>
|
>
|
||||||
<HcpNavItem @list={{SNL}}/>
|
<DataSource @src={{uri '/${partition}/*/${dc}/hcp-link' (hash dc=@dc partition=@partition name=@dc)}} as |hcpLink|>
|
||||||
|
<HcpNavItem @list={{SNL}} @linkData={{hcpLink.data}} />
|
||||||
|
</DataSource>
|
||||||
<Consul::Datacenter::Selector
|
<Consul::Datacenter::Selector
|
||||||
@list={{SNL}}
|
@list={{SNL}}
|
||||||
@dc={{@dc}}
|
@dc={{@dc}}
|
||||||
|
|
|
@ -11,5 +11,24 @@
|
||||||
@isHrefExternal={{true}}
|
@isHrefExternal={{true}}
|
||||||
data-test-back-to-hcp
|
data-test-back-to-hcp
|
||||||
/>
|
/>
|
||||||
|
{{else}}
|
||||||
|
{{#if this.shouldDisplayNavLinkItem}}
|
||||||
|
{{#if this.alreadyLinked}}
|
||||||
|
<SNL.Link
|
||||||
|
@text="HCP Consul Central"
|
||||||
|
@href={{hcp-resource-id-to-link @linkData.resourceId}}
|
||||||
|
@isHrefExternal={{true}}
|
||||||
|
@badge="Linked"
|
||||||
|
data-test-linked-cluster-hcp-link
|
||||||
|
/>
|
||||||
|
{{else}}
|
||||||
|
<SNL.Item data-test-link-to-hcp>
|
||||||
|
<button type="button" class="hds-side-nav__list-item-link hcp-nav-item" {{on "click" this.onLinkToConsulCentral}}>
|
||||||
|
<Hds::Text::Body @size='200'>Link to HCP Consul Central</Hds::Text::Body>
|
||||||
|
<FlightIcon class='w-4 h-4' @size='24' @name='arrow-right'/>
|
||||||
|
</button>
|
||||||
|
</SNL.Item>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/let}}
|
{{/let}}
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
import Component from '@glimmer/component';
|
import Component from '@glimmer/component';
|
||||||
import { inject as service } from '@ember/service';
|
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
|
* 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 {
|
export default class HcpLinkItemComponent extends Component {
|
||||||
@service env;
|
@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() {
|
get shouldShowBackToHcpItem() {
|
||||||
const isConsulHcpUrlDefined = !!this.env.var('CONSUL_HCP_URL');
|
const isConsulHcpUrlDefined = !!this.env.var('CONSUL_HCP_URL');
|
||||||
const isConsulHcpEnabled = !!this.env.var('CONSUL_HCP_ENABLED');
|
const isConsulHcpEnabled = !!this.env.var('CONSUL_HCP_ENABLED');
|
||||||
return isConsulHcpEnabled && isConsulHcpUrlDefined;
|
return isConsulHcpEnabled && isConsulHcpUrlDefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
onLinkToConsulCentral() {
|
||||||
|
// TODO: https://hashicorp.atlassian.net/browse/CC-7147 open the modal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,12 +10,17 @@ const LOCAL_STORAGE_KEY = 'consul:hideHcpLinkBanner';
|
||||||
|
|
||||||
export default class HcpLinkStatus extends Service {
|
export default class HcpLinkStatus extends Service {
|
||||||
@service('env') env;
|
@service('env') env;
|
||||||
|
@service abilities;
|
||||||
@tracked
|
@tracked
|
||||||
userDismissedBanner = false;
|
userDismissedBanner = false;
|
||||||
|
|
||||||
get shouldDisplayBanner() {
|
get shouldDisplayBanner() {
|
||||||
const hcpLinkEnabled = this.env.var('CONSUL_HCP_LINK_ENABLED');
|
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() {
|
constructor() {
|
||||||
|
|
|
@ -7,6 +7,44 @@ import RepositoryService from 'consul-ui/services/repository';
|
||||||
import dataSource from 'consul-ui/decorators/data-source';
|
import dataSource from 'consul-ui/decorators/data-source';
|
||||||
|
|
||||||
export default class HcpLinkService extends RepositoryService {
|
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')
|
@dataSource('/:partition/:ns/:dc/hcp-link')
|
||||||
async fetch({ partition, ns, dc }, { uri }, request) {
|
async fetch({ partition, ns, dc }, { uri }, request) {
|
||||||
let result;
|
let result;
|
||||||
|
@ -16,15 +54,19 @@ export default class HcpLinkService extends RepositoryService {
|
||||||
GET /api/hcp/v2/link/global
|
GET /api/hcp/v2/link/global
|
||||||
`
|
`
|
||||||
)((headers, body) => {
|
)((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 {
|
return {
|
||||||
meta: {
|
meta: {
|
||||||
version: 2,
|
version: 2,
|
||||||
uri: uri,
|
uri: uri,
|
||||||
},
|
},
|
||||||
body: {
|
body: {
|
||||||
isLinked: (body.status['consul.io/hcp/link']['conditions'] || []).some(
|
isLinked,
|
||||||
(condition) => condition.type === 'linked' && condition.state === 'STATE_TRUE'
|
resourceId,
|
||||||
),
|
|
||||||
},
|
},
|
||||||
headers,
|
headers,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
{
|
{
|
||||||
|
"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": {
|
"status": {
|
||||||
"consul.io/hcp/link": {
|
"consul.io/hcp/link": {
|
||||||
"conditions": [
|
"conditions": [
|
||||||
|
|
|
@ -9,7 +9,8 @@ import { setupApplicationTest } from 'ember-qunit';
|
||||||
import { EnvStub } from 'consul-ui/services/env';
|
import { EnvStub } from 'consul-ui/services/env';
|
||||||
|
|
||||||
const bannerSelector = '[data-test-link-to-hcp-banner]';
|
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);
|
setupApplicationTest(hooks);
|
||||||
|
|
||||||
hooks.beforeEach(function () {
|
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) {
|
test('the banner and nav item are initially displayed on services page', async function (assert) {
|
||||||
assert.expect(3);
|
|
||||||
// default route is services page so we're good here
|
// default route is services page so we're good here
|
||||||
await visit('/');
|
await visit('/');
|
||||||
// Expect the banner to be visible by default
|
// 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
|
// Click on the dismiss button
|
||||||
await click(`${bannerSelector} button[aria-label="Dismiss"]`);
|
await click(`${bannerSelector} button[aria-label="Dismiss"]`);
|
||||||
assert.dom(bannerSelector).doesNotExist('Banner is gone after dismissing');
|
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
|
// Refresh the page
|
||||||
await visit('/');
|
await visit('/');
|
||||||
assert.dom(bannerSelector).doesNotExist('Banner is still gone after refresh');
|
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) {
|
test('the banner is not displayed if the env var is not set', async function (assert) {
|
|
@ -8,11 +8,18 @@ import { setupRenderingTest } from 'ember-qunit';
|
||||||
import { render } from '@ember/test-helpers';
|
import { render } from '@ember/test-helpers';
|
||||||
import hbs from 'htmlbars-inline-precompile';
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
import { EnvStub } from 'consul-ui/services/env';
|
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) {
|
module('Integration | Component | hcp nav item', function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test('it prints the value of CONSUL_HCP_URL', async function (assert) {
|
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(
|
this.owner.register(
|
||||||
'service:env',
|
'service:env',
|
||||||
class Stub extends EnvStub {
|
class Stub extends EnvStub {
|
||||||
|
@ -29,8 +36,12 @@ module('Integration | Component | hcp nav item', function (hooks) {
|
||||||
</Hds::SideNav::List>
|
</Hds::SideNav::List>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
assert.dom('[data-test-back-to-hcp]').isVisible();
|
assert.dom(backToHcpSelector).isVisible();
|
||||||
assert.dom('a').hasAttribute('href', 'http://hcp.com');
|
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) {
|
test('it does not output the Back to HCP link if CONSUL_HCP_URL is not present', async function (assert) {
|
||||||
|
@ -50,7 +61,7 @@ module('Integration | Component | hcp nav item', function (hooks) {
|
||||||
</Hds::SideNav::List>
|
</Hds::SideNav::List>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
assert.dom('[data-test-back-to-hcp]').doesNotExist();
|
assert.dom(backToHcpSelector).doesNotExist();
|
||||||
assert.dom('a').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) {
|
test('it does not output the Back to HCP link if CONSUL_HCP_ENABLED is not present', async function (assert) {
|
||||||
|
@ -70,7 +81,155 @@ module('Integration | Component | hcp nav item', function (hooks) {
|
||||||
</Hds::SideNav::List>
|
</Hds::SideNav::List>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
assert.dom('[data-test-back-to-hcp]').doesNotExist();
|
assert.dom(backToHcpSelector).doesNotExist();
|
||||||
assert.dom('a').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`
|
||||||
|
<Hds::SideNav::List as |SNL|>
|
||||||
|
<HcpNavItem @list={{SNL}} @linkData={{this.linkData}}/>
|
||||||
|
</Hds::SideNav::List>
|
||||||
|
`);
|
||||||
|
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`
|
||||||
|
<Hds::SideNav::List as |SNL|>
|
||||||
|
<HcpNavItem @list={{SNL}} @linkData={{this.linkData}}/>
|
||||||
|
</Hds::SideNav::List>
|
||||||
|
`);
|
||||||
|
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`
|
||||||
|
<Hds::SideNav::List as |SNL|>
|
||||||
|
<HcpNavItem @list={{SNL}} @linkData={{this.linkData}}/>
|
||||||
|
</Hds::SideNav::List>
|
||||||
|
`);
|
||||||
|
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`
|
||||||
|
<Hds::SideNav::List as |SNL|>
|
||||||
|
<HcpNavItem @list={{SNL}} @linkData={{this.linkData}}/>
|
||||||
|
</Hds::SideNav::List>
|
||||||
|
`);
|
||||||
|
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`
|
||||||
|
<Hds::SideNav::List as |SNL|>
|
||||||
|
<HcpNavItem @list={{SNL}} @linkData={{this.linkData}}/>
|
||||||
|
</Hds::SideNav::List>
|
||||||
|
`);
|
||||||
|
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`
|
||||||
|
<Hds::SideNav::List as |SNL|>
|
||||||
|
<HcpNavItem @list={{SNL}} @linkData={{this.linkData}}/>
|
||||||
|
</Hds::SideNav::List>
|
||||||
|
`);
|
||||||
|
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');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -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(), '');
|
||||||
|
});
|
||||||
|
});
|
|
@ -10,9 +10,8 @@ import { setupTest } from 'ember-qunit';
|
||||||
module('Unit | Ability | *', function (hooks) {
|
module('Unit | Ability | *', function (hooks) {
|
||||||
setupTest(hooks);
|
setupTest(hooks);
|
||||||
|
|
||||||
// Replace this with your real tests.
|
|
||||||
test('it exists', function (assert) {
|
test('it exists', function (assert) {
|
||||||
assert.expect(228);
|
assert.expect(240);
|
||||||
|
|
||||||
const abilities = Object.keys(requirejs.entries)
|
const abilities = Object.keys(requirejs.entries)
|
||||||
.filter((key) => key.indexOf('/abilities/') !== -1)
|
.filter((key) => key.indexOf('/abilities/') !== -1)
|
||||||
|
|
Loading…
Reference in New Issue