From 3740bb079a28c26af1f88353850db597519fa89a Mon Sep 17 00:00:00 2001
From: Lisbet Alvarez <107949262+lisbet-alvarez@users.noreply.github.com>
Date: Fri, 22 Sep 2023 11:52:14 -0700
Subject: [PATCH] Icu-11111 don't display empty modal when a target has no
target address and no host sources (#1909)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* fix: 🐛 disable connect buttons & add message
✅ Closes: ICU-11111
* test: 💍 add test cases
* fix: 🐛 buttons on list view & add getter to target model
* refactor: 💡 use can ability instead and remove Promise.all
* test: 💍 fix expect number
---
addons/core/translations/resources/en-us.yaml | 3 +
ui/desktop/app/abilities/target.js | 16 +++++
.../scopes/scope/projects/targets/target.hbs | 61 ++++++++++++-------
ui/desktop/tests/acceptance/targets-test.js | 35 ++++++++++-
.../tests/unit/abilities/target-test.js | 30 +++++++++
5 files changed, 121 insertions(+), 24 deletions(-)
create mode 100644 ui/desktop/app/abilities/target.js
create mode 100644 ui/desktop/tests/unit/abilities/target-test.js
diff --git a/addons/core/translations/resources/en-us.yaml b/addons/core/translations/resources/en-us.yaml
index f12baf9a3..c0f94b306 100644
--- a/addons/core/translations/resources/en-us.yaml
+++ b/addons/core/translations/resources/en-us.yaml
@@ -551,6 +551,9 @@ target:
connect-more-info:
title: Connect for more info
description: Additional information for this target will be provided here after your session is established.
+ cannot-connect:
+ title: Cannot connect to {targetDisplayName}
+ description: No host sources and no target address found. Please update target with address information to connect directly. Otherwise, add at least one host to connect using host sources.
titles:
new: New Target
actions:
diff --git a/ui/desktop/app/abilities/target.js b/ui/desktop/app/abilities/target.js
new file mode 100644
index 000000000..40c420212
--- /dev/null
+++ b/ui/desktop/app/abilities/target.js
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import TargetAbility from 'api/abilities/target';
+
+export default class OverrideTargetAbility extends TargetAbility {
+ /**
+ *
+ * @type {boolean}
+ */
+ get canInitiateConnection() {
+ return this.model.address || this.model.host_sources?.length;
+ }
+}
diff --git a/ui/desktop/app/templates/scopes/scope/projects/targets/target.hbs b/ui/desktop/app/templates/scopes/scope/projects/targets/target.hbs
index 441cfced8..94bcd80bb 100644
--- a/ui/desktop/app/templates/scopes/scope/projects/targets/target.hbs
+++ b/ui/desktop/app/templates/scopes/scope/projects/targets/target.hbs
@@ -15,34 +15,51 @@
-
+ {{#if (can 'connect target' @model.target)}}
+
+ {{/if}}
-
+ {{#if (can 'initiateConnection target' @model.target)}}
+
+ {{/if}}
-
-
+ {{#if (can 'initiateConnection target' @model.target)}}
+
+
+ {{else}}
+
+
+ {{/if}}
diff --git a/ui/desktop/tests/acceptance/targets-test.js b/ui/desktop/tests/acceptance/targets-test.js
index 2ea8a5678..3cca4e681 100644
--- a/ui/desktop/tests/acceptance/targets-test.js
+++ b/ui/desktop/tests/acceptance/targets-test.js
@@ -4,7 +4,7 @@
*/
import { module, test } from 'qunit';
-import { visit, currentURL } from '@ember/test-helpers';
+import { visit, click, currentURL } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
import a11yAudit from 'ember-a11y-testing/test-support/audit';
@@ -19,6 +19,9 @@ module('Acceptance | targets', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
+ const TARGET_CONNECT_BUTTON = '[data-test-target-detail-connect-button]';
+ const APP_STATE_TITLE = '.hds-application-state__title';
+
const instances = {
scopes: {
global: null,
@@ -29,6 +32,7 @@ module('Acceptance | targets', function (hooks) {
global: null,
},
target: null,
+ emptyTarget: null,
};
const stubs = {
@@ -49,6 +53,8 @@ module('Acceptance | targets', function (hooks) {
},
projects: null,
targets: null,
+ target: null,
+ emptyTarget: null,
};
const setDefaultClusterUrl = (test) => {
@@ -85,9 +91,12 @@ module('Acceptance | targets', function (hooks) {
);
instances.target = this.server.create(
'target',
- { scope: instances.scopes.project },
+ { scope: instances.scopes.project, address: '127.0.0.1' },
'withAssociations'
);
+ instances.emptyTarget = this.server.create('target', {
+ scope: instances.scopes.project,
+ });
urls.scopes.global = `/scopes/${instances.scopes.global.id}`;
urls.scopes.org = `/scopes/${instances.scopes.org.id}`;
@@ -95,6 +104,8 @@ module('Acceptance | targets', function (hooks) {
urls.authenticate.methods.global = `${urls.authenticate.global}/${instances.authMethods.global.id}`;
urls.projects = `${urls.scopes.org}/projects`;
urls.targets = `${urls.projects}/targets`;
+ urls.target = `${urls.targets}/${instances.target.id}`;
+ urls.emptyTarget = `${urls.targets}/${instances.emptyTarget.id}`;
// Mock the postMessage interface used by IPC.
this.owner.register('service:browser/window', WindowMockIPC);
@@ -115,4 +126,24 @@ module('Acceptance | targets', function (hooks) {
await visit(urls.targets);
assert.strictEqual(currentURL(), urls.targets);
});
+
+ test('cannot connect to a target without an address and no host sources', async function (assert) {
+ assert.expect(2);
+ await visit(urls.targets);
+
+ await click(`[href="${urls.emptyTarget}"]`);
+
+ assert.dom(TARGET_CONNECT_BUTTON).isDisabled();
+ assert.dom(APP_STATE_TITLE).includesText('Cannot connect');
+ });
+
+ test('can connect to a target with an address', async function (assert) {
+ assert.expect(2);
+ await visit(urls.targets);
+
+ await click(`[href="${urls.target}"]`);
+
+ assert.dom(TARGET_CONNECT_BUTTON).isEnabled();
+ assert.dom(APP_STATE_TITLE).includesText('Connect for more info');
+ });
});
diff --git a/ui/desktop/tests/unit/abilities/target-test.js b/ui/desktop/tests/unit/abilities/target-test.js
new file mode 100644
index 000000000..2299590ab
--- /dev/null
+++ b/ui/desktop/tests/unit/abilities/target-test.js
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Abilities | target', function (hooks) {
+ setupTest(hooks);
+
+ test('it reflects when a target can initiate connection or not', function (assert) {
+ assert.expect(5);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ address: '',
+ };
+ assert.false(service.can('initiateConnection target', model));
+ model.host_sources = [];
+ assert.false(service.can('initiateConnection target', model));
+ model.address = 'localhost';
+ assert.true(service.can('initiateConnection target', model));
+ model.address = '';
+ model.host_sources = ['host_123'];
+ assert.true(service.can('initiateConnection target', model));
+ model.address = 'localhost';
+ model.host_sources = ['host_123'];
+ assert.true(service.can('initiateConnection target', model));
+ });
+});