diff --git a/ui/core/app/components/form/host-set/hosts/index.hbs b/ui/core/app/components/form/host-set/hosts/index.hbs
deleted file mode 100644
index 6fb9e5158..000000000
--- a/ui/core/app/components/form/host-set/hosts/index.hbs
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
- {{!--
- {{#if @model.errors.host_ids}}
-
- {{#each @model.errors.host_ids as |error|}}
- {{error.message}}
- {{/each}}
-
- {{/if}}
- --}}
-
-
-
-
- {{t 'form.id.label'}}
- {{t 'form.name.label'}}
- {{t 'form.address.label'}}
-
-
-
- {{#each this.options as |option|}}
-
-
-
-
- {{option.host.name}}
- {{option.host.attributes.address}}
-
- {{/each}}
-
-
-
-
diff --git a/ui/core/app/components/form/host-set/hosts/index.js b/ui/core/app/components/form/host-set/hosts/index.js
deleted file mode 100644
index 5b6484bc9..000000000
--- a/ui/core/app/components/form/host-set/hosts/index.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import Component from '@glimmer/component';
-import { computed } from '@ember/object';
-
-export default class FormHostSetHostsComponent extends Component {
- // =attributes
-
- /**
- * An array of wrapped `HostModel` instances where the wrapper includes
- * a `selected` boolean field indicating if the host is represented
- * in `model.host_ids`.
- * @type {[{host: HostModel, selected: boolean}]}
- */
- @computed('args.{hosts.[],model.host_ids.[]}')
- get options() {
- const { hosts, model: hostSet } = this.args;
- return hosts.map((host) => ({
- host,
- selected: Boolean(hostSet.host_ids.findBy('value', host.id)),
- }));
- }
-}
diff --git a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js
index 75fd25649..d892490ab 100644
--- a/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js
+++ b/ui/core/app/routes/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/add-hosts.js
@@ -64,25 +64,6 @@ export default class ScopesScopeProjectsProjectHostCatalogsHostCatalogHostSetsHo
// =actions
- /**
- * Toggles the presence of the passed host ID in the passed host set's
- * `host_ids` field.
- * @param {HostSetModel} hostSet
- * @param {HostModel} host
- */
- @action
- toggleHost(hostSet, host) {
- const isHostSelected = Boolean(hostSet.host_ids.findBy('value', host.id));
- const fragment = hostSet.host_ids.findBy('value', host.id);
- if (isHostSelected) {
- // if host is already selected, filter it out
- hostSet.host_ids.removeObject(fragment);
- } else {
- // if host is not selected, add it
- hostSet.host_ids.addObject({ value: host.id });
- }
- }
-
/**
* Saves host IDs on the host set.
* @param {HostSetModel} hostSet
diff --git a/ui/core/tests/acceptance/host-sets/hosts-test.js b/ui/core/tests/acceptance/host-sets/hosts-test.js
new file mode 100644
index 000000000..2bd0d6997
--- /dev/null
+++ b/ui/core/tests/acceptance/host-sets/hosts-test.js
@@ -0,0 +1,162 @@
+import { module, test } from 'qunit';
+import { visit, currentURL, click, find, findAll } 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';
+import { Response } from 'miragejs';
+import {
+ authenticateSession,
+ // These are left here intentionally for future reference.
+ //currentSession,
+ //invalidateSession,
+} from 'ember-simple-auth/test-support';
+
+module('Acceptance | host-sets | hosts', function (hooks) {
+ setupApplicationTest(hooks);
+ setupMirage(hooks);
+
+ const instances = {
+ scopes: {
+ global: null,
+ org: null,
+ project: null,
+ },
+ hostCatalog: null,
+ hostSet: null,
+ };
+ const urls = {
+ orgScope: null,
+ projects: null,
+ project: null,
+ hostCatalogs: null,
+ hostCatalog: null,
+ hostSets: null,
+ hostSet: null,
+ hostSetHosts: null
+ };
+ let hostSetHostsCount;
+
+ hooks.beforeEach(function () {
+ // Setup Mirage mock resources for this test
+ authenticateSession();
+ instances.scopes.global = this.server.create('scope', { id: 'global' });
+ instances.scopes.org = this.server.create('scope', {
+ type: 'org',
+ scope: { id: 'global', type: 'global' },
+ });
+ instances.scopes.project = this.server.create('scope', {
+ type: 'project',
+ scope: { id: instances.scopes.org.id, type: 'org' },
+ });
+ instances.hostCatalog = this.server.create('host-catalog', {
+ scope: instances.scopes.project,
+ }, 'withChildren');
+ instances.hostSet = this.server.schema.hostSets.all().models[0];
+ // Generate route URLs for resources
+ urls.orgScope = `/scopes/${instances.scopes.org.id}`;
+ urls.projects = `${urls.orgScope}/projects`;
+ urls.project = `${urls.projects}/${instances.hostCatalog.scope.id}`;
+ urls.hostCatalogs = `${urls.project}/host-catalogs`;
+ urls.hostCatalog = `${urls.hostCatalogs}/${instances.hostCatalog.id}`;
+ urls.hostSets = `${urls.hostCatalog}/host-sets`;
+ urls.hostSet = `${urls.hostSets}/${instances.hostSet.id}`;
+ urls.hostSetHosts = `${urls.hostSet}/hosts`;
+ urls.addHosts = `${urls.hostSet}/add-hosts`;
+ // Counts
+ hostSetHostsCount = instances.hostSet.hosts.length;
+ });
+
+ test('visiting host set hosts', async function (assert) {
+ assert.expect(2);
+ await visit(urls.hostSetHosts);
+ await a11yAudit();
+ assert.equal(currentURL(), urls.hostSetHosts);
+ assert.equal(findAll('tbody tr').length, hostSetHostsCount);
+ });
+
+ test('can remove a host', async function (assert) {
+ assert.expect(2);
+ await visit(urls.hostSetHosts);
+ assert.equal(findAll('tbody tr').length, hostSetHostsCount);
+ await click('tbody tr .rose-dropdown-button-danger');
+ assert.equal(findAll('tbody tr').length, hostSetHostsCount - 1);
+ });
+
+ test('shows error message on host remove error', async function (assert) {
+ assert.expect(2);
+ this.server.post('/host-sets/:idMethod', () => {
+ return new Response(
+ 400,
+ {},
+ {
+ status: 400,
+ code: 'invalid_argument',
+ message: 'The request was invalid.',
+ details: {},
+ }
+ );
+ });
+ await visit(urls.hostSetHosts);
+ assert.equal(findAll('tbody tr').length, hostSetHostsCount);
+ await click('tbody tr .rose-dropdown-button-danger');
+ assert.ok(find('[role="alert"]'));
+ });
+
+ test('visiting add hosts', async function(assert) {
+ assert.expect(1);
+ await visit(urls.addHosts);
+ await a11yAudit();
+ assert.equal(currentURL(), urls.addHosts);
+ });
+
+ test('select and save hosts to add', async function (assert) {
+ assert.expect(3);
+ instances.hostSet.update({ hostIds: [] });
+ await visit(urls.hostSetHosts);
+ assert.equal(findAll('tbody tr').length, 0);
+ await click('.rose-layout-page-actions a')
+ assert.equal(currentURL(), urls.addHosts);
+ // Click three times to select, unselect, then reselect (for coverage)
+ await click('tbody label');
+ await click('tbody label');
+ await click('tbody label');
+ await click('form [type="submit"]');
+ await visit(urls.hostSetHosts);
+ assert.equal(findAll('tbody tr').length, 1);
+ });
+
+ test('select and cancel hosts to add', async function (assert) {
+ assert.expect(4);
+ await visit(urls.hostSetHosts);
+ assert.equal(findAll('tbody tr').length, hostSetHostsCount);
+ await click('tbody tr .rose-dropdown-button-danger');
+ assert.equal(findAll('tbody tr').length, hostSetHostsCount - 1);
+ await click('.rose-layout-page-actions a')
+ assert.equal(currentURL(), urls.addHosts);
+ await click('tbody label');
+ await click('form [type="button"]');
+ await visit(urls.hostSetHosts);
+ assert.equal(findAll('tbody tr').length, hostSetHostsCount - 1);
+ });
+
+ test('shows error message on host add error', async function (assert) {
+ assert.expect(1);
+ this.server.post('/host-sets/:idMethod', () => {
+ return new Response(
+ 400,
+ {},
+ {
+ status: 400,
+ code: 'invalid_argument',
+ message: 'The request was invalid.',
+ details: {},
+ }
+ );
+ });
+ instances.hostSet.update({ hostIds: [] });
+ await visit(urls.addHosts);
+ await click('tbody label');
+ await click('form [type="submit"]');
+ assert.ok(find('[role="alert"]'));
+ });
+});
diff --git a/ui/core/tests/integration/components/form/host-set/hosts-test.js b/ui/core/tests/integration/components/form/host-set/hosts-test.js
deleted file mode 100644
index e5d2bfe87..000000000
--- a/ui/core/tests/integration/components/form/host-set/hosts-test.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import { module, test } from 'qunit';
-import { setupRenderingTest } from 'ember-qunit';
-import { render, find } from '@ember/test-helpers';
-import { hbs } from 'ember-cli-htmlbars';
-
-module('Integration | Component | form/host-set/hosts', function (hooks) {
- setupRenderingTest(hooks);
-
- test('it renders', async function (assert) {
- this.submit = () => {};
- this.cancel = () => {};
- this.model = { host_ids: [] };
- this.hosts = [];
-
- await render(hbs`
- `);
-
- assert.ok(find('form'));
- });
-});