refactor: 💡 remove route-action usage for targets and sessions (#2528)
* refactor: 💡 remove route-action usage for targets and sessions ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-15040
This commit is contained in:
1 parent
1b31188d5e
commit
0f52b86364
14 files changed
+551
-136
No files matched your search
@@ -13,7 +13,6 @@ module.exports = {
|
||||
'no-bare-strings': true,
|
||||
'no-curly-component-invocation': { allow: ['app-name'] },
|
||||
'no-implicit-this': { allow: ['app-name', 'is-loading'] },
|
||||
'no-route-action': false,
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
|
||||
@@ -7,6 +7,8 @@ import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { action } from '@ember/object';
|
||||
import { loading } from 'ember-loading';
|
||||
import { notifySuccess, notifyError } from 'core/decorators/notify';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import {
|
||||
STATUS_SESSION_ACTIVE,
|
||||
@@ -19,6 +21,11 @@ export default class ScopesScopeProjectsSessionsIndexController extends Controll
|
||||
// =services
|
||||
|
||||
@service intl;
|
||||
@service store;
|
||||
@service ipc;
|
||||
@service session;
|
||||
@service router;
|
||||
@service can;
|
||||
|
||||
// =attributes
|
||||
|
||||
@@ -108,4 +115,42 @@ export default class ScopesScopeProjectsSessionsIndexController extends Controll
|
||||
this[filter] = [...selectedItems];
|
||||
this.page = 1;
|
||||
}
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Cancels the specified session and notifies user of success or error.
|
||||
* @param {SessionModel}
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(({ message }) => message, { catch: true })
|
||||
@notifySuccess('notifications.canceled-success')
|
||||
async cancelSession(session) {
|
||||
let updatedSession = session;
|
||||
// fetch session from API to verify we have most up to date record
|
||||
if (this.can.can('read session', session)) {
|
||||
updatedSession = await this.store.findRecord('session', session.id, {
|
||||
reload: true,
|
||||
});
|
||||
}
|
||||
|
||||
await updatedSession.cancelSession();
|
||||
|
||||
await this.ipc.invoke('stop', { session_id: session.id });
|
||||
if (
|
||||
this.router.currentRoute.name ===
|
||||
'scopes.scope.projects.sessions.session.index'
|
||||
) {
|
||||
this.router.replaceWith('scopes.scope.projects.targets.index');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the all data for the current page.
|
||||
*/
|
||||
@action
|
||||
refresh() {
|
||||
this.send('refreshAll');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeProjectsSessionsSessionController extends Controller {
|
||||
@controller('scopes/scope/projects/sessions/index') sessions;
|
||||
}
|
||||
@@ -304,4 +304,12 @@ export default class ScopesScopeProjectsTargetsIndexController extends Controlle
|
||||
await this.ipc.invoke('stop', { session_id: session.id });
|
||||
this.router.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the all data for the current page.
|
||||
*/
|
||||
@action
|
||||
refresh() {
|
||||
this.send('refreshAll');
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,25 @@
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { action } from '@ember/object';
|
||||
|
||||
export default class ScopesScopeProjectsTargetsTargetController extends Controller {
|
||||
@controller('scopes/scope/projects/targets/index') targets;
|
||||
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service confirm;
|
||||
|
||||
// =attributes
|
||||
|
||||
queryParams = [{ isConnecting: { type: 'boolean' } }];
|
||||
|
||||
@tracked isConnecting = false;
|
||||
isConnectionError = false;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -20,4 +29,64 @@ export default class ScopesScopeProjectsTargetsTargetController extends Controll
|
||||
toggleModal(value) {
|
||||
this.isConnecting = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect method that calls parent connect method and handles
|
||||
* connection errors unique to this route
|
||||
* @param {TargetModel} target
|
||||
* @param {HostModel} host
|
||||
*/
|
||||
@action
|
||||
async connect(target, host) {
|
||||
try {
|
||||
await this.targets.connect(target, host);
|
||||
} catch (error) {
|
||||
this.isConnectionError = true;
|
||||
this.confirm
|
||||
.confirm(error.message, { isConnectError: true })
|
||||
// Retry
|
||||
.then(() => this.connect(target, host))
|
||||
.catch(() => {
|
||||
// Reset the flag as this was user initiated and we're not
|
||||
// in a transition or have a host modal open
|
||||
this.isConnectionError = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish a session to current target.
|
||||
* @param {TargetModel} target
|
||||
* @param {HostModel} host
|
||||
* hostConnect is only called when making a connection with a host and ensures that the host modal is automatically closed in the case of a connection error.
|
||||
*/
|
||||
@action
|
||||
async hostConnect(target, host) {
|
||||
await this.connect(target, host);
|
||||
|
||||
if (this.isConnectionError) {
|
||||
this.toggleModal(false);
|
||||
this.isConnectionError = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if we show host modal or quick connect based on target attributes.
|
||||
* @param {TargetModel} model
|
||||
* @param {function} toggleModal
|
||||
*/
|
||||
@action
|
||||
async preConnect(model) {
|
||||
/**
|
||||
* if hosts length is 1 or less we will try to
|
||||
* connect, even if there is no address on the target and
|
||||
* rely on the CLI to give the user the proper error or if
|
||||
* there are 2 or more hosts we show the modal for host selection
|
||||
*/
|
||||
if (model.hosts.length <= 1) {
|
||||
await this.connect(model.target);
|
||||
} else {
|
||||
this.toggleModal(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,18 +5,12 @@
|
||||
|
||||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import { notifySuccess, notifyError } from 'core/decorators/notify';
|
||||
import { loading } from 'ember-loading';
|
||||
|
||||
export default class ScopesScopeProjectsSessionsRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service ipc;
|
||||
@service session;
|
||||
@service router;
|
||||
@service can;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -26,42 +20,4 @@ export default class ScopesScopeProjectsSessionsRoute extends Route {
|
||||
beforeModel() {
|
||||
if (!this.session.isAuthenticated) this.router.transitionTo('index');
|
||||
}
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Cancels the specified session and notifies user of success or error.
|
||||
* @param {SessionModel}
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(({ message }) => message, { catch: true })
|
||||
@notifySuccess('notifications.canceled-success')
|
||||
async cancelSession(session) {
|
||||
let updatedSession = session;
|
||||
// fetch session from API to verify we have most up to date record
|
||||
if (this.can.can('read session', session)) {
|
||||
updatedSession = await this.store.findRecord('session', session.id, {
|
||||
reload: true,
|
||||
});
|
||||
}
|
||||
|
||||
await updatedSession.cancelSession();
|
||||
|
||||
await this.ipc.invoke('stop', { session_id: session.id });
|
||||
if (
|
||||
this.router.currentRoute.name ===
|
||||
'scopes.scope.projects.sessions.session.index'
|
||||
) {
|
||||
this.router.replaceWith('scopes.scope.projects.targets.index');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* refreshes session data.
|
||||
*/
|
||||
@action
|
||||
async refreshSessions() {
|
||||
return this.refresh();
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,6 @@ export default class ScopesScopeProjectsTargetsTargetRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service confirm;
|
||||
|
||||
// =attributes
|
||||
|
||||
isConnectionError = false;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -73,7 +68,11 @@ export default class ScopesScopeProjectsTargetsTargetRoute extends Route {
|
||||
* rely on the CLI to give the user the proper error
|
||||
*/
|
||||
if (isConnecting && model.hosts.length <= 1) {
|
||||
await this.connect(model.target);
|
||||
/* eslint-disable-next-line ember/no-controller-access-in-routes */
|
||||
const controller = this.controllerFor(
|
||||
'scopes.scope.projects.targets.target',
|
||||
);
|
||||
await controller.connect(model.target);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,82 +82,14 @@ export default class ScopesScopeProjectsTargetsTargetRoute extends Route {
|
||||
*/
|
||||
@action
|
||||
didTransition() {
|
||||
if (this.isConnectionError) {
|
||||
/* eslint-disable-next-line ember/no-controller-access-in-routes */
|
||||
const controller = this.controllerFor(
|
||||
'scopes.scope.projects.targets.target',
|
||||
);
|
||||
/* eslint-disable-next-line ember/no-controller-access-in-routes */
|
||||
const controller = this.controllerFor(
|
||||
'scopes.scope.projects.targets.target',
|
||||
);
|
||||
if (controller.get('isConnectionError')) {
|
||||
controller.set('isConnecting', false);
|
||||
this.isConnectionError = false;
|
||||
controller.set('isConnectionError', false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect method that calls parent connect method and handles
|
||||
* connection errors unique to this route
|
||||
* @param {TargetModel} target
|
||||
* @param {HostModel} host
|
||||
*/
|
||||
@action
|
||||
async connect(target, host) {
|
||||
/* eslint-disable-next-line ember/no-controller-access-in-routes */
|
||||
const parentController = this.controllerFor(
|
||||
'scopes.scope.projects.targets.index',
|
||||
);
|
||||
try {
|
||||
await parentController.connect(target, host);
|
||||
} catch (error) {
|
||||
this.isConnectionError = true;
|
||||
this.confirm
|
||||
.confirm(error.message, { isConnectError: true })
|
||||
// Retry
|
||||
.then(() => this.connect(target, host))
|
||||
.catch(() => {
|
||||
// Reset the flag as this was user initiated and we're not
|
||||
// in a transition or have a host modal open
|
||||
this.isConnectionError = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish a session to current target.
|
||||
* @param {TargetModel} target
|
||||
* @param {HostModel} host
|
||||
* hostConnect is only called when making a connection with a host and ensures that the host modal is automatically closed in the case of a connection error.
|
||||
*/
|
||||
@action
|
||||
async hostConnect(target, host) {
|
||||
await this.connect(target, host);
|
||||
|
||||
if (this.isConnectionError) {
|
||||
/* eslint-disable-next-line ember/no-controller-access-in-routes */
|
||||
const controller = this.controllerFor(
|
||||
'scopes.scope.projects.targets.target',
|
||||
);
|
||||
controller.set('isConnecting', false);
|
||||
this.isConnectionError = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if we show host modal or quick connect based on target attributes.
|
||||
* @param {TargetModel} model
|
||||
* @param {function} toggleModal
|
||||
*/
|
||||
@action
|
||||
async preConnect(model, toggleModal) {
|
||||
/**
|
||||
* if hosts length is 1 or less we will try to
|
||||
* connect, even if there is no address on the target and
|
||||
* rely on the CLI to give the user the proper error or if
|
||||
* there are 2 or more hosts we show the modal for host selection
|
||||
*/
|
||||
if (model.hosts.length <= 1) {
|
||||
await this.connect(model.target);
|
||||
} else {
|
||||
toggleModal(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@
|
||||
</Dropdown>
|
||||
</S.Generic>
|
||||
</Hds::SegmentedGroup>
|
||||
<ToolbarRefresher @onClick={{route-action 'refreshAll'}} />
|
||||
<ToolbarRefresher @onClick={{this.refresh}} />
|
||||
</div>
|
||||
|
||||
<FilterTags @filters={{this.filters}} />
|
||||
@@ -143,7 +143,7 @@
|
||||
@icon='x'
|
||||
@isIconOnly={{true}}
|
||||
@color='secondary'
|
||||
{{on 'click' (route-action 'cancelSession' B.data)}}
|
||||
{{on 'click' (fn this.cancelSession B.data)}}
|
||||
data-test-session-cancel-button={{B.data.id}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
@text={{t 'resources.session.actions.end'}}
|
||||
@icon='x'
|
||||
@color='secondary'
|
||||
{{on 'click' (route-action 'cancelSession' @model)}}
|
||||
{{on 'click' (fn this.sessions.cancelSession @model)}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
</S.Generic>
|
||||
</Hds::SegmentedGroup>
|
||||
{{#if @model.isCacheRefreshing}}
|
||||
<ToolbarRefresher @onClick={{route-action 'refreshAll'}}>
|
||||
<ToolbarRefresher @onClick={{this.refresh}}>
|
||||
<Hds::TooltipButton
|
||||
@text={{t 'states.incomplete-loading.refreshing.tooltip'}}
|
||||
>
|
||||
@@ -73,7 +73,7 @@
|
||||
</Hds::TooltipButton>
|
||||
</ToolbarRefresher>
|
||||
{{else}}
|
||||
<ToolbarRefresher @onClick={{route-action 'refreshAll'}} />
|
||||
<ToolbarRefresher @onClick={{this.refresh}} />
|
||||
{{/if}}
|
||||
</div>
|
||||
<FilterTags @filters={{this.filters}} />
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
@text={{t 'resources.session.actions.connect'}}
|
||||
@icon='entry-point'
|
||||
@iconPosition='trailing'
|
||||
{{on 'click' (route-action 'preConnect' @model this.toggleModal)}}
|
||||
{{on 'click' (fn this.preConnect @model)}}
|
||||
/>
|
||||
{{/if}}
|
||||
</page.actions>
|
||||
@@ -31,7 +31,7 @@
|
||||
<Target::HostModal
|
||||
@showModal={{this.isConnecting}}
|
||||
@toggleModal={{this.toggleModal}}
|
||||
@connect={{route-action 'hostConnect'}}
|
||||
@connect={{this.hostConnect}}
|
||||
@hosts={{@model.hosts}}
|
||||
@target={{@model.target}}
|
||||
/>
|
||||
|
||||
@@ -5,18 +5,143 @@
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { setupIntl } from 'ember-intl/test-support';
|
||||
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
|
||||
import setupStubs from 'api/test-support/handlers/cache-daemon-search';
|
||||
import { visit } from '@ember/test-helpers';
|
||||
import { authenticateSession } from 'ember-simple-auth/test-support';
|
||||
import {
|
||||
STATUS_SESSION_ACTIVE,
|
||||
STATUS_SESSION_PENDING,
|
||||
STATUS_SESSION_CANCELING,
|
||||
STATUS_SESSION_TERMINATED,
|
||||
} from 'api/models/session';
|
||||
|
||||
module(
|
||||
'Unit | Controller | scopes/scope/projects/sessions/index',
|
||||
function (hooks) {
|
||||
setupTest(hooks);
|
||||
setupMirage(hooks);
|
||||
setupStubs(hooks);
|
||||
setupIntl(hooks, 'en-us');
|
||||
|
||||
// TODO: Replace this with your real tests.
|
||||
test('it exists', function (assert) {
|
||||
let controller = this.owner.lookup(
|
||||
let store;
|
||||
let controller;
|
||||
|
||||
const instances = {
|
||||
scopes: {
|
||||
global: null,
|
||||
org: null,
|
||||
project: null,
|
||||
},
|
||||
target: null,
|
||||
session: null,
|
||||
};
|
||||
|
||||
const urls = {
|
||||
projectScope: null,
|
||||
sessions: null,
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
authenticateSession({});
|
||||
store = this.owner.lookup('service:store');
|
||||
controller = this.owner.lookup(
|
||||
'controller:scopes/scope/projects/sessions/index',
|
||||
);
|
||||
|
||||
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.target = this.server.create('target', {
|
||||
scope: instances.scopes.project,
|
||||
});
|
||||
instances.session = this.server.create('session', {
|
||||
scope: instances.scopes.project,
|
||||
target: instances.target,
|
||||
status: STATUS_SESSION_ACTIVE,
|
||||
});
|
||||
|
||||
urls.projectScope = `/scopes/${instances.scopes.org.id}/projects`;
|
||||
urls.sessions = `${urls.projectScope}/sessions`;
|
||||
|
||||
this.ipcStub.withArgs('isCacheDaemonRunning').returns(true);
|
||||
this.stubCacheDaemonSearch('sessions', 'sessions', 'targets');
|
||||
});
|
||||
|
||||
test('it exists', function (assert) {
|
||||
this.stubCacheDaemonSearch();
|
||||
assert.ok(controller);
|
||||
});
|
||||
|
||||
test('sortedSessions returns a sessions sorted by status', async function (assert) {
|
||||
this.server.create('session', {
|
||||
scope: instances.scopes.org,
|
||||
target: instances.target,
|
||||
status: STATUS_SESSION_CANCELING,
|
||||
});
|
||||
this.stubCacheDaemonSearch('sessions', 'sessions', 'targets');
|
||||
await visit(urls.sessions);
|
||||
|
||||
const sortedSessions = controller.sortedSessions;
|
||||
|
||||
assert.strictEqual(sortedSessions[0].status, STATUS_SESSION_ACTIVE);
|
||||
assert.strictEqual(sortedSessions[1].status, STATUS_SESSION_CANCELING);
|
||||
});
|
||||
|
||||
test('sessionStatusOptions returns expected object', function (assert) {
|
||||
this.stubCacheDaemonSearch();
|
||||
|
||||
assert.deepEqual(controller.sessionStatusOptions, [
|
||||
{ id: STATUS_SESSION_ACTIVE, name: 'Active' },
|
||||
{ id: STATUS_SESSION_PENDING, name: 'Pending' },
|
||||
{ id: STATUS_SESSION_CANCELING, name: 'Canceling' },
|
||||
{ id: STATUS_SESSION_TERMINATED, name: 'Terminated' },
|
||||
]);
|
||||
});
|
||||
|
||||
test('availableScopes returns all existing project scopes', async function (assert) {
|
||||
await visit(urls.sessions);
|
||||
const project = await store.findRecord(
|
||||
'scope',
|
||||
instances.scopes.project.id,
|
||||
);
|
||||
|
||||
assert.deepEqual(controller.availableScopes, [project]);
|
||||
});
|
||||
|
||||
test('filters returns expected entries', async function (assert) {
|
||||
await visit(urls.sessions);
|
||||
|
||||
assert.ok(controller.filters.allFilters);
|
||||
assert.ok(controller.filters.selectedFilters);
|
||||
});
|
||||
|
||||
test('applyFilter action sets expected values correctly', async function (assert) {
|
||||
this.stubCacheDaemonSearch();
|
||||
const selectedItems = ['yes'];
|
||||
controller.applyFilter('availableSessions', selectedItems);
|
||||
|
||||
assert.strictEqual(controller.page, 1);
|
||||
assert.deepEqual(controller.availableSessions, selectedItems);
|
||||
});
|
||||
|
||||
test('cancelSession action action updates session status', async function (assert) {
|
||||
await visit(urls.sessions);
|
||||
|
||||
const session = await store.findRecord('session', instances.session.id);
|
||||
|
||||
assert.strictEqual(session.status, STATUS_SESSION_ACTIVE);
|
||||
|
||||
await controller.cancelSession(session);
|
||||
|
||||
assert.strictEqual(session.status, STATUS_SESSION_CANCELING);
|
||||
});
|
||||
},
|
||||
);
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module(
|
||||
'Unit | Controller | scopes/scope/projects/sessions/session',
|
||||
function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('it exists', function (assert) {
|
||||
let controller = this.owner.lookup(
|
||||
'controller:scopes/scope/projects/sessions/session',
|
||||
);
|
||||
assert.ok(controller);
|
||||
assert.ok(controller.sessions);
|
||||
});
|
||||
},
|
||||
);
|
||||
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { setupIntl } from 'ember-intl/test-support';
|
||||
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
|
||||
import setupStubs from 'api/test-support/handlers/cache-daemon-search';
|
||||
import { waitUntil, visit } from '@ember/test-helpers';
|
||||
import { authenticateSession } from 'ember-simple-auth/test-support';
|
||||
import {
|
||||
STATUS_SESSION_ACTIVE,
|
||||
STATUS_SESSION_PENDING,
|
||||
STATUS_SESSION_CANCELING,
|
||||
} from 'api/models/session';
|
||||
import { TYPE_TARGET_SSH, TYPE_TARGET_TCP } from 'api/models/target';
|
||||
|
||||
module(
|
||||
'Unit | Controller | scopes/scope/projects/targets/index',
|
||||
function (hooks) {
|
||||
setupTest(hooks);
|
||||
setupMirage(hooks);
|
||||
setupStubs(hooks);
|
||||
setupIntl(hooks, 'en-us');
|
||||
|
||||
let store;
|
||||
let controller;
|
||||
|
||||
const instances = {
|
||||
scopes: {
|
||||
global: null,
|
||||
org: null,
|
||||
project: null,
|
||||
},
|
||||
target: null,
|
||||
session: null,
|
||||
};
|
||||
|
||||
const urls = {
|
||||
projectScope: null,
|
||||
targets: null,
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
authenticateSession({});
|
||||
store = this.owner.lookup('service:store');
|
||||
controller = this.owner.lookup(
|
||||
'controller:scopes/scope/projects/targets/index',
|
||||
);
|
||||
|
||||
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.target = this.server.create('target', {
|
||||
scope: instances.scopes.org,
|
||||
});
|
||||
instances.session = this.server.create('session', {
|
||||
scope: instances.scopes.org,
|
||||
target: instances.target,
|
||||
status: STATUS_SESSION_ACTIVE,
|
||||
});
|
||||
|
||||
urls.projectScope = `/scopes/${instances.scopes.org.id}/projects`;
|
||||
urls.targets = `${urls.projectScope}/targets`;
|
||||
|
||||
this.ipcStub.withArgs('isCacheDaemonRunning').returns(true);
|
||||
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');
|
||||
});
|
||||
|
||||
test('it exists', function (assert) {
|
||||
this.stubCacheDaemonSearch();
|
||||
assert.ok(controller);
|
||||
assert.ok(controller.refresh);
|
||||
});
|
||||
|
||||
test('noResults returns falsy when targets exist', async function (assert) {
|
||||
await visit(urls.targets);
|
||||
|
||||
assert.notOk(controller.noResults);
|
||||
});
|
||||
|
||||
test('noResults returns truthy when no targets exist but there is a search term', async function (assert) {
|
||||
this.server.schema.targets.all().destroy();
|
||||
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');
|
||||
controller.search = 'target that does not exist';
|
||||
await visit(urls.targets);
|
||||
|
||||
assert.ok(controller.noResults);
|
||||
});
|
||||
|
||||
test('noTargets returns truthy when no targets exist', async function (assert) {
|
||||
this.server.schema.targets.all().destroy();
|
||||
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');
|
||||
await visit(urls.targets);
|
||||
|
||||
assert.ok(controller.noTargets);
|
||||
});
|
||||
|
||||
test('noTargets returns falsy when targets exist', async function (assert) {
|
||||
await visit(urls.targets);
|
||||
|
||||
assert.notOk(controller.noTargets);
|
||||
});
|
||||
|
||||
test('availableScopes returns all existing project scopes', async function (assert) {
|
||||
await visit(urls.targets);
|
||||
const project = await store.findRecord(
|
||||
'scope',
|
||||
instances.scopes.project.id,
|
||||
);
|
||||
|
||||
assert.deepEqual(controller.availableScopes, [project]);
|
||||
});
|
||||
|
||||
test('availableSessionOptions returns expected object', function (assert) {
|
||||
this.stubCacheDaemonSearch();
|
||||
|
||||
assert.deepEqual(controller.availableSessionOptions, [
|
||||
{ id: 'yes', name: 'Has active sessions' },
|
||||
{ id: 'no', name: 'No active sessions' },
|
||||
]);
|
||||
});
|
||||
|
||||
test('sortedTargetSessions returns a limit of 10 items sorted by created time descending', async function (assert) {
|
||||
this.server.create('session', {
|
||||
scope: instances.scopes.org,
|
||||
target: instances.target,
|
||||
status: STATUS_SESSION_ACTIVE,
|
||||
});
|
||||
controller.selectedTarget = await store.findRecord(
|
||||
'target',
|
||||
instances.target.id,
|
||||
);
|
||||
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');
|
||||
await visit(urls.targets);
|
||||
|
||||
const sortedSessions = controller.sortedTargetSessions;
|
||||
|
||||
assert.true(sortedSessions.length <= 10);
|
||||
assert.true(
|
||||
sortedSessions[0].created_time >= sortedSessions[1].created_time,
|
||||
);
|
||||
assert.false(controller.showFlyoutViewMoreLink);
|
||||
});
|
||||
|
||||
test('viewMoreLinkQueryParams returns expected object', async function (assert) {
|
||||
this.stubCacheDaemonSearch();
|
||||
controller.selectedTarget = instances.target;
|
||||
|
||||
assert.deepEqual(controller.viewMoreLinkQueryParams, {
|
||||
targets: [instances.target.id],
|
||||
status: [STATUS_SESSION_ACTIVE, STATUS_SESSION_PENDING],
|
||||
});
|
||||
});
|
||||
|
||||
test('targetTypeOptions returns expected target types', async function (assert) {
|
||||
this.stubCacheDaemonSearch();
|
||||
|
||||
assert.deepEqual(controller.targetTypeOptions, [
|
||||
{ id: TYPE_TARGET_TCP, name: 'Generic TCP' },
|
||||
{ id: TYPE_TARGET_SSH, name: 'SSH' },
|
||||
]);
|
||||
});
|
||||
|
||||
test('filters returns expected entries', async function (assert) {
|
||||
await visit(urls.targets);
|
||||
|
||||
assert.ok(controller.filters.allFilters);
|
||||
assert.ok(controller.filters.selectedFilters);
|
||||
});
|
||||
|
||||
test('handleSearchInput action sets expected values correctly', async function (assert) {
|
||||
this.stubCacheDaemonSearch();
|
||||
const searchValue = 'test';
|
||||
controller.handleSearchInput({ target: { value: searchValue } });
|
||||
await waitUntil(() => controller.search === searchValue);
|
||||
|
||||
assert.strictEqual(controller.page, 1);
|
||||
assert.strictEqual(controller.search, searchValue);
|
||||
});
|
||||
|
||||
test('toggleSessionsFlyout action sets expected value correctly', async function (assert) {
|
||||
this.stubCacheDaemonSearch();
|
||||
controller.sessionsFlyoutActive = false;
|
||||
|
||||
assert.false(controller.sessionsFlyoutActive);
|
||||
|
||||
controller.toggleSessionsFlyout();
|
||||
|
||||
assert.true(controller.sessionsFlyoutActive);
|
||||
|
||||
controller.toggleSessionsFlyout();
|
||||
|
||||
assert.false(controller.sessionsFlyoutActive);
|
||||
});
|
||||
|
||||
test('applyFilter action sets expected values correctly', async function (assert) {
|
||||
this.stubCacheDaemonSearch();
|
||||
const selectedItems = ['yes'];
|
||||
controller.applyFilter('availableSessions', selectedItems);
|
||||
|
||||
assert.strictEqual(controller.page, 1);
|
||||
assert.deepEqual(controller.availableSessions, selectedItems);
|
||||
});
|
||||
|
||||
test('selectTarget action sets expected value correctly', async function (assert) {
|
||||
this.stubCacheDaemonSearch();
|
||||
|
||||
assert.notOk(controller.selectedTarget);
|
||||
|
||||
controller.selectTarget(instances.target);
|
||||
|
||||
assert.deepEqual(controller.selectedTarget, instances.target);
|
||||
});
|
||||
|
||||
test('connect action creates a session with correct info and cancelSession action updates session status', async function (assert) {
|
||||
const attrs = {
|
||||
session_id: instances.session.id,
|
||||
address: 'a_123',
|
||||
port: 'p_123',
|
||||
};
|
||||
this.ipcStub.withArgs('cliExists').returns(true);
|
||||
this.ipcStub.withArgs('connect').returns(attrs);
|
||||
await visit(urls.targets);
|
||||
const target = await store.findRecord('target', instances.target.id);
|
||||
const session = await store.findRecord('session', instances.session.id);
|
||||
|
||||
assert.notOk(session.proxy_address);
|
||||
assert.notOk(session.proxy_port);
|
||||
|
||||
await controller.connect(target);
|
||||
|
||||
assert.strictEqual(session.proxy_address, attrs.address);
|
||||
assert.strictEqual(session.proxy_port, attrs.port);
|
||||
|
||||
await controller.cancelSession(session);
|
||||
await visit(urls.projectScope);
|
||||
|
||||
assert.strictEqual(session.status, STATUS_SESSION_CANCELING);
|
||||
});
|
||||
},
|
||||
);
|
||||
Reference in new issue
Block a user