Refactor origin to cluster (#1210)

This commit is contained in:
Carlos Alcaide Corvo authored and GitHub committed 2022-07-27 10:25:01 -07:00
1 parent 40ba4286d3
commit 4fcb005a1f
43 files changed
+492 -609

No files matched your search

+1 -1
View File
@@ -159,7 +159,7 @@ You will need to turn `off` mirage and run it: `$ ENABLE_MIRAGE=false yarn start
In login screen, authenticate using generated admin login name and password.
Enter the origin of your Boundary dev instance, by default is: `http://localhost:9200`.
Enter the cluster URL of your Boundary dev instance, by default is: `http://localhost:9200`.
### Committing
+8 -8
View File
@@ -15,19 +15,19 @@ export default function initializeMockIPC(server, config) {
return await this[method](payload);
}
origin = null;
clusterUrl = null;
getOrigin() {
return this.origin;
getClusterUrl() {
return this.clusterUrl;
}
setOrigin(origin) {
this.origin = origin;
return this.origin;
setClusterUrl(clusterUrl) {
this.clusterUrl = clusterUrl;
return this.clusterUrl;
}
resetOrigin() {
this.origin = null;
resetClusterUrl() {
this.clusterUrl = null;
}
openExternal(href) {
+1 -1
View File
@@ -31,7 +31,7 @@ add-hosts: Add Hosts
set-password: Set Password
change-password: Change Password
edit-form: Edit Form
change-origin: Change Origin URL
change-cluster-url: Change Cluster URL
change-state: Change State
close: Close
toggle-secret: Toggle secret visibility
+2 -2
View File
@@ -9,7 +9,7 @@ auth:
authenticating-with-org: "Scope: You are authenticating with organization \"{name}\""
flow-success: You've successfully authenticated. You may now close this window and return to the client.
flow-error: Something went wrong while authenticating. Please close this window and try again. If the problem persists, notify your administrator.
origin:
cluster-url:
connected-to: Connected to
titles:
home: Home
@@ -36,7 +36,7 @@ titles:
create-resources: Create Resources
descriptions:
empty-set: There are no items to display yet. You may be able to add items or try back later.
origin-initialization: To get started, please enter your origin URL
cluster-url-initialization: To get started, please enter your cluster URL
create-but-not-list: You do not have permission to list {resource}, but you can create new instances.
neither-list-nor-create: You do not have permission to list or create {resource}.
no-results: We found no matching records.
+2 -2
View File
@@ -17,7 +17,7 @@ generic:
title: Error
authentication-failed:
title: Authentication Failed
origin-verification-failed:
description: Unable to connect to the specified origin. Please check the URL and try again.
cluster-url-verification-failed:
description: Unable to connect to the specified cluster URL. Please check the URL and try again.
quick-setup-failed:
description: We're sorry, quick setup was unable to generate all resources.
+3 -3
View File
@@ -49,8 +49,8 @@ host_set:
grant_scope:
label: Grant Scope
help: Specify the scope to which this role applies.
origin:
label: Origin URL
cluster-url:
label: Cluster URL
description: The Boundary URL to which to connect (e.g. protocol://host:port)
proxy:
label: Proxy
@@ -148,4 +148,4 @@ ip_addresses:
label: Latest IP Addresses
sync-interval:
label: Sync Interval
help: Number of seconds between the time Boundary syncs hosts in this set.
help: Number of seconds between the time Boundary syncs hosts in this set.
@@ -23,7 +23,7 @@ export default class OnboardingQuickSetupCreateResourcesSuccessRoute extends Rou
const model = this.modelFor('onboarding.quick-setup.create-resources');
return {
...model,
origin: this.window.location.origin,
clusterUrl: this.window.location.origin,
};
}
@@ -48,11 +48,11 @@
<p>{{t 'onboarding.success.descriptions.controller'}}</p>
<div class='onboarding-quick-setup-success-controller-url'>
<Copyable
@text={{this.model.origin}}
@text={{this.model.clusterUrl}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{this.model.origin}}</code>
<code>{{this.model.clusterUrl}}</code>
</Copyable>
</div>
</div>
@@ -15,98 +15,6 @@
<dialog.body>
{{yield to='body'}}
{{!--
<Rose::Separator />
<h3>Credentials</h3>
<div class="credentials-card">
<div class="credentials-card-header">
<div><Rose::Icon @name="key" /> Credentials</div>
<div>
<Rose::Button
@disabled={{false}}
@style={{style}}
@iconRight={{iconRight}}
{{on "click" onClick}}
>
Credential library details
</Rose::Button>
</div>
</div>
<Rose::Separator />
<div class="credentials-card-body">
<Rose::Table @style="condensed" as |table|>
<table.header as |header|>
<header.row as |row|>
<row.headerCell @shrink={{true}}>Key</row.headerCell>
<row.headerCell colspan="2">Value</row.headerCell>
</header.row>
</table.header>
<table.body as |body|>
<body.row as |row|>
<row.cell>Foo</row.cell>
<row.cell>&nbsp;</row.cell>
</body.row>
<body.row as |row|>
<row.cell>ttl</row.cell>
<row.cell>&nbsp;</row.cell>
</body.row>
</table.body>
</Rose::Table>
</div>
<div class="credentials-card-footer">
<p><LinkTo @route='index'>View raw API output</LinkTo></p>
<Rose::Separator />
<div>Code</div>
</div>
</div>
<div class="credentials-card">
<div class="credentials-card-header">
<div><Rose::Icon @name="key" /> Credentials</div>
<div>
<Rose::Button
@disabled={{false}}
@style={{style}}
@iconRight={{iconRight}}
{{on "click" onClick}}
>
Credential library details
</Rose::Button>
</div>
</div>
<Rose::Separator />
<div class="credentials-card-body">
<Rose::Table @style="condensed" as |table|>
<table.header as |header|>
<header.row as |row|>
<row.headerCell @shrink={{true}}>Key</row.headerCell>
<row.headerCell colspan="2">Value</row.headerCell>
</header.row>
</table.header>
<table.body as |body|>
<body.row as |row|>
<row.cell>Foo</row.cell>
<row.cell>&nbsp;</row.cell>
</body.row>
<body.row as |row|>
<row.cell>ttl</row.cell>
<row.cell>&nbsp;</row.cell>
</body.row>
</table.body>
</Rose::Table>
</div>
<div class="credentials-card-footer">
<p><LinkTo @route='index'>View raw API output</LinkTo></p>
<Rose::Separator />
<div>Code</div>
</div>
</div>--}}
</dialog.body>
<dialog.footer>
{{yield to='footer'}}
@@ -4,7 +4,7 @@ import { inject as service } from '@ember/service';
export default class ScopesScopeAuthenticateController extends Controller {
// =services
@service origin;
@service clusterUrl;
// =attributes
@@ -11,10 +11,10 @@ export function initialize(registry) {
this._super(...arguments);
const originalBeforeModel = this.beforeModel;
// Override the beforeModel hook and initialize the origin
// Override the beforeModel hook and initialize the clusterUrl
this.beforeModel = async function () {
const origin = getOwner(this).lookup('service:origin');
return origin.updateOrigin().then(
const clusterUrl = getOwner(this).lookup('service:clusterUrl');
return clusterUrl.updateClusterUrl().then(
() => originalBeforeModel.apply(this, arguments),
() => originalBeforeModel.apply(this, arguments)
);
+1 -1
View File
@@ -25,5 +25,5 @@ Router.map(function () {
});
});
});
this.route('origin');
this.route('cluster-url');
});
+7 -7
View File
@@ -9,7 +9,7 @@ export default class ApplicationRoute extends Route {
// =services
@service session;
@service origin;
@service clusterUrl;
@service ipc;
// =attributes
@@ -20,14 +20,14 @@ export default class ApplicationRoute extends Route {
routeIfUnauthenticated = 'index';
/**
* Check that the origin specified in the renderer matches the origin
* Check that the clusterUrl specified in the renderer matches the clusterUrl
* reported by the main process. If they differ, update the main process
* origin so that the renderer's CSP can be rewritten to allow requests.
* clusterUrl so that the renderer's CSP can be rewritten to allow requests.
*/
beforeModel() {
const theme = this.session.get('data.theme');
this.toggleTheme(theme);
return this.origin.updateOrigin();
return this.clusterUrl.updateClusterUrl();
}
/**
@@ -52,12 +52,12 @@ export default class ApplicationRoute extends Route {
}
/**
* Disconnects from origin and invalidates session, thereby resetting
* the client and reloading to the onboarding origin screen.
* Disconnects from clusterUrl and invalidates session, thereby resetting
* the client and reloading to the onboarding clusterUrl screen.
*/
@action
disconnect() {
this.origin.resetOrigin();
this.clusterUrl.resetClusterUrl();
this.invalidateSession();
}
@@ -5,11 +5,11 @@ import { action } from '@ember/object';
import { loading } from 'ember-loading';
import config from '../config/environment';
export default class OriginRoute extends Route {
export default class ClusterUrlRoute extends Route {
// =services
@service session;
@service origin;
@service clusterUrl;
@service intl;
@service notify;
@service router;
@@ -38,45 +38,45 @@ export default class OriginRoute extends Route {
/**
* If arriving here already authenticated, redirect to index for further
* processing. User must be logged out before changing the origin.
* processing. User must be logged out before changing the clusterUrl.
*/
beforeModel() {
if (this.session.isAuthenticated) this.router.replaceWith('index');
}
/**
* Adds the existing origin, if any, to the controller scope.
* Adds the existing clusterUrl, if any, to the controller scope.
* @param {Controller} controller
*/
setupController(controller) {
super.setupController(...arguments);
let origin = this.origin.rendererOrigin;
// If origin is unset and this is a development environment,
// autoset the origin field of the UI for better DX.
let clusterUrl = this.clusterUrl.rendererClusterUrl;
// If clusterUrl is unset and this is a development environment,
// autoset the clusterUrl field of the UI for better DX.
// The controller URL is almost always the same as the current window when
// using mocks, and this makes development more rapid since developers
// do not need to fill an origin on every session.
if (!origin && config.autoOrigin) {
origin = this.window.location.origin;
// do not need to fill a clusterUrl on every session.
if (!clusterUrl && config.autoOrigin) {
clusterUrl = this.window.location.origin;
}
controller.setProperties({ origin });
controller.setProperties({ clusterUrl: clusterUrl });
}
/**
* Points the API to the specified origin. When the main process receives
* the origin, it is expected that the renderer will be restarted.
* @param {string} origin
* Points the API to the specified clusterUrl. When the main process receives
* the clusterUrl, it is expected that the renderer will be restarted.
* @param {string} clusterUrl
*/
@action
@loading
async setOrigin(origin) {
async setClusterUrl(clusterUrl) {
try {
await this.origin.setOrigin(origin);
await this.clusterUrl.setClusterUrl(clusterUrl);
this.router.replaceWith('index');
} catch (e) {
// If scopes do not load, we assume this is not a Boundary API
const errorMessage = this.intl.t(
'errors.origin-verification-failed.description'
'errors.cluster-url-verification-failed.description'
);
this.notify.error(errorMessage, { closeAfter: null });
}
+5 -5
View File
@@ -4,18 +4,18 @@ import { inject as service } from '@ember/service';
export default class IndexRoute extends Route {
// =services
@service origin;
@service clusterUrl;
@service router;
// =methods
/**
* If no origin is specified yet, redirects to origin, otherwise scopes.
* If no clusterUrl is specified yet, redirects to cluster-url, otherwise scopes.
*/
redirect() {
const rendererOrigin = this.origin.rendererOrigin;
if (!rendererOrigin) {
this.router.replaceWith('origin');
const rendererClusterUrl = this.clusterUrl.rendererClusterUrl;
if (!rendererClusterUrl) {
this.router.replaceWith('cluster-url');
} else {
this.router.replaceWith('scopes');
}
@@ -6,7 +6,7 @@ export default class ScopesScopeAuthenticateRoute extends Route {
// =services
@service session;
@service origin;
@service clusterUrl;
@service router;
// =methods
@@ -31,16 +31,16 @@ export default class ScopesScopeAuthenticateRoute extends Route {
}
redirect() {
if (!this.origin.rendererOrigin) this.router.replaceWith('index');
if (!this.clusterUrl.rendererClusterUrl) this.router.replaceWith('index');
}
/**
* Adds the existing origin, if any, to the controller scope.
* Adds the existing clusterUrl, if any, to the controller scope.
* @param {Controller} controller
*/
setupController(controller) {
super.setupController(...arguments);
const origin = this.origin.rendererOrigin;
controller.setProperties({ origin });
const clusterUrl = this.clusterUrl.rendererClusterUrl;
controller.setProperties({ clusterUrl });
}
}
@@ -12,7 +12,7 @@ export default class ScopesScopeProjectsTargetsRoute extends Route {
@service ipc;
@service session;
@service origin;
@service clusterUrl;
@service notify;
@service confirm;
@service resourceFilterStore;
@@ -7,7 +7,7 @@ export default class ScopesScopeProjectsTargetsTargetHostsRoute extends Route {
@service ipc;
@service session;
@service origin;
@service clusterUrl;
@service notify;
@service confirm;
+91
View File
@@ -0,0 +1,91 @@
import Service from '@ember/service';
import { assert } from '@ember/debug';
import { inject as service } from '@ember/service';
import { notifyError } from 'core/decorators/notify';
export default class ClusterUrlService extends Service {
// =services
@service ipc;
@service store;
@service storage;
// =attributes
/**
* @type {ApplicationAdapter}
*/
get adapter() {
return this.store.adapterFor('application');
}
/**
* @type {?string}
*/
get rendererClusterUrl() {
return this.storage.getItem('cluster-url');
}
/**
* @param {?string} clusterUrl
*/
set rendererClusterUrl(clusterUrl) {
this.storage.setItem('cluster-url', clusterUrl);
}
/**
* @type {Promise{?string}}
*/
get mainClusterUrl() {
return this.ipc.invoke('getClusterUrl');
}
// =methods
/**
* Sets the main clusterUrl equal to the current renderer clusterUrl (if any).
*/
async updateClusterUrl() {
const rendererClusterUrl = this.rendererClusterUrl;
if (rendererClusterUrl) await this.setClusterUrl(rendererClusterUrl);
}
/**
* Validates that the specified clusterUrl is a Boundary API. If so, the app is
* updated to use the clusterUrl. If it is not a Boundary API, or an clusterUrl
* wasn't specified, throws an error.
* @param {string} clusterUrl - protocol://host:port
*/
async setClusterUrl(clusterUrl) {
const originalHost = this.adapter.host;
assert(
`setClusterUrl expects a string, you passed ${clusterUrl}`,
typeof clusterUrl === 'string'
);
try {
// Trim whitespaces and silently drop trailing slashes if present.
// This is important since API paths that will be appended to the clusterUrl
// will include preceeding slashes already.
clusterUrl = clusterUrl.trim();
clusterUrl = clusterUrl.replace(/\/*$/, '');
this.adapter.host = clusterUrl;
this.rendererClusterUrl = clusterUrl;
if (clusterUrl !== (await this.mainClusterUrl)) {
await this.ipc.invoke('setClusterUrl', clusterUrl);
}
} catch (e) {
this.adapter.host = originalHost;
this.rendererClusterUrl = null;
throw e;
}
}
/**
* Resets the clusterUrl.
*/
@notifyError(({ message }) => message, { catch: true })
async resetClusterUrl() {
this.rendererClusterUrl = null;
await this.ipc.invoke('resetClusterUrl');
}
}
-91
View File
@@ -1,91 +0,0 @@
import Service from '@ember/service';
import { assert } from '@ember/debug';
import { inject as service } from '@ember/service';
import { notifyError } from 'core/decorators/notify';
export default class OriginService extends Service {
// =services
@service ipc;
@service store;
@service storage;
// =attributes
/**
* @type {ApplicationAdapter}
*/
get adapter() {
return this.store.adapterFor('application');
}
/**
* @type {?string}
*/
get rendererOrigin() {
return this.storage.getItem('origin');
}
/**
* @param {?string} origin
*/
set rendererOrigin(origin) {
this.storage.setItem('origin', origin);
}
/**
* @type {Promise{?string}}
*/
get mainOrigin() {
return this.ipc.invoke('getOrigin');
}
// =methods
/**
* Sets the main origin equal to the current renderer origin (if any).
*/
async updateOrigin() {
const rendererOrigin = this.rendererOrigin;
if (rendererOrigin) await this.setOrigin(rendererOrigin);
}
/**
* Validates that the specified origin is a Boundary API. If so, the app is
* updated to use the origin. If it is not a Boundary API, or an origin
* wasn't specified, throws an error.
* @param {string} origin - protocol://host:port
*/
async setOrigin(origin) {
const originalHost = this.adapter.host;
assert(
`setOrigin expects a string, you passed ${origin}`,
typeof origin === 'string'
);
try {
// Trim whitespaces and silently drop trailing slashes if present.
// This is important since API paths that will be appended to the origin
// will include preceeding slashes already.
origin = origin.trim();
origin = origin.replace(/\/*$/, '');
this.adapter.host = origin;
this.rendererOrigin = origin;
if (origin !== (await this.mainOrigin)) {
await this.ipc.invoke('setOrigin', origin);
}
} catch (e) {
this.adapter.host = originalHost;
this.rendererOrigin = null;
throw e;
}
}
/**
* Resets the origin.
*/
@notifyError(({ message }) => message, { catch: true })
async resetOrigin() {
this.rendererOrigin = null;
await this.ipc.invoke('resetOrigin');
}
}
@@ -1,11 +1,11 @@
<main>
<BrandedCard
@title={{t 'titles.welcome-to-boundary'}}
@description={{t 'descriptions.origin-initialization'}}
@description={{t 'descriptions.cluster-url-initialization'}}
>
<Rose::Form
class='full-width'
@onSubmit={{route-action 'setOrigin' this.origin}}
@onSubmit={{route-action 'setClusterUrl' this.clusterUrl}}
@cancel={{false}}
@disabled={{(is-loading)}}
as |form|
@@ -13,9 +13,9 @@
<form.input
@name='host'
@type='text'
@value={{this.origin}}
@label={{t 'form.origin.label'}}
@helperText={{t 'form.origin.description'}}
@value={{this.clusterUrl}}
@label={{t 'form.cluster-url.label'}}
@helperText={{t 'form.cluster-url.description'}}
{{autofocus}}
/>
<form.actions @submitText={{t 'actions.submit'}} @showCancel={{false}} />
@@ -62,11 +62,11 @@
{{outlet}}
<p class='change-origin'>
{{t 'origin.connected-to'}}:
<code>{{this.origin}}</code>
{{t 'cluster-url.connected-to'}}:
<code>{{this.clusterUrl}}</code>
<br />
<LinkTo @route='origin'>
{{t 'actions.change-origin'}}
<LinkTo @route='cluster-url'>
{{t 'actions.change-cluster-url'}}
</LinkTo>
</p>
@@ -27,10 +27,10 @@ const enableDevCSP = () => {
const generateCSPHeader = () => {
const policy = Object.assign({}, csp);
// If an origin is specified, add it to the connect-src directive
if (runtimeSettings.origin) {
// If a clusterUrl is specified, add it to the connect-src directive
if (runtimeSettings.clusterUrl) {
policy['connect-src'] = policy['connect-src'].slice();
policy['connect-src'].push(runtimeSettings.origin);
policy['connect-src'].push(runtimeSettings.clusterUrl);
}
return Object.keys(policy)
+2 -2
View File
@@ -83,9 +83,9 @@ const createWindow = (partition, closeWindowCB) => {
const browserWindow = new BrowserWindow(browserWindowOptions);
// If the user-specified origin changes, reload the page so that
// If the user-specified cluster URL changes, reload the page so that
// the CSP can be refreshed with the this source allowed
runtimeSettings.onOriginChange(() => browserWindow.loadURL(emberAppURL));
runtimeSettings.onClusterUrlChange(() => browserWindow.loadURL(emberAppURL));
// Load the ember application
browserWindow.loadURL(emberAppURL);
+10 -10
View File
@@ -8,25 +8,25 @@ const sanitizer = require('../utils/sanitizer.js');
const { isMac } = require('../helpers/platform.js');
/**
* Returns the current runtime origin, which is used by the main thread to
* Returns the current runtime clusterUrl, which is used by the main thread to
* rewrite the CSP to allow requests.
*/
handle('getOrigin', () => runtimeSettings.origin);
handle('getClusterUrl', () => runtimeSettings.clusterUrl);
/**
* Sets the origin to be used in the content security policy and triggers
* Sets the clusterUrl to be used in the content security policy and triggers
* a main window reload.
*/
handle('setOrigin', async (requestOrigin) => {
const origin = sanitizer.urlValidate(requestOrigin);
await runtimeSettings.validateOrigin(origin);
runtimeSettings.origin = origin;
handle('setClusterUrl', async (requestOrigin) => {
const clusterUrl = sanitizer.urlValidate(requestOrigin);
await runtimeSettings.validateClusterUrl(clusterUrl);
runtimeSettings.clusterUrl = clusterUrl;
});
/**
* Resets the origin.
* Resets the clusterUrl.
*/
handle('resetOrigin', async () => runtimeSettings.resetOrigin());
handle('resetClusterUrl', async () => runtimeSettings.resetClusterUrl());
/**
* Opens the specified URL in an external browser. Only secure HTTPs URLs are
@@ -60,7 +60,7 @@ handle('cliExists', () => boundaryCli.exists());
* Establishes a boundary session and returns session details.
*/
handle('connect', ({ target_id, token, host_id }) =>
sessionManager.start(runtimeSettings.origin, target_id, token, host_id)
sessionManager.start(runtimeSettings.clusterUrl, target_id, token, host_id)
);
/**
@@ -1,35 +1,35 @@
const netRequestPromise = require('../helpers/net-request-promise.js');
// Runtime settings are any configuration, especially user-specified,
// set up at runtime. For example, the Boundary origin is a runtime setting.
// set up at runtime. For example, the Boundary clusterUrl is a runtime setting.
class RuntimeSettings {
// Internal private origin is exposed via getter/setter below.
#origin = undefined;
// Internal private clusterUrl is exposed via getter/setter below.
#clusterUrl = undefined;
/**
* The user-specified Boundary origin, which should be allowed by CSP.
* The user-specified Boundary clusterUrl, which should be allowed by CSP.
* @type {?string}
*/
get origin() {
return this.#origin;
get clusterUrl() {
return this.#clusterUrl;
}
set origin(origin) {
if (this.#origin !== origin) {
this.#origin = origin;
this.triggerOriginChanged();
set clusterUrl(clusterUrl) {
if (this.#clusterUrl !== clusterUrl) {
this.#clusterUrl = clusterUrl;
this.triggerClusterUrlChanged();
}
}
/**
* Validates the origin is reachable and has a scopes endpoint.
* Validates the clusterUrl is reachable and has a scopes endpoint.
*/
async validateOrigin(origin) {
// If the origin is the Electron origin, it is automatically valid.
if (origin === 'serve://boundary') return true;
// Otherwise, check if scopes can be loaded from the specified origin.
async validateClusterUrl(clusterUrl) {
// If the clusterUrl is the Electron clusterUrl, it is automatically valid.
if (clusterUrl === 'serve://boundary') return true;
// Otherwise, check if scopes can be loaded from the specified clusterUrl.
// Scopes are required by the desktop client, so this is a simple smoke
// test to see if the origin is API-compatible with the desktop client.
const scopesEndpoint = `${origin}/v1/scopes`;
// test to see if the clusterUrl is API-compatible with the desktop client.
const scopesEndpoint = `${clusterUrl}/v1/scopes`;
try {
const result = await netRequestPromise(scopesEndpoint);
// Redirects (3xx) are handled in the netRequest Promise, so we only
@@ -38,27 +38,27 @@ class RuntimeSettings {
throw new Error();
}
} catch (e) {
throw new Error(`Origin ${origin} could not be validated.`);
throw new Error(`Cluster URL ${clusterUrl} could not be validated.`);
}
}
/**
* Sets the origin to null.
* Sets the clusterUrl to null.
*/
async resetOrigin() {
this.origin = null;
async resetClusterUrl() {
this.#clusterUrl = null;
}
// Quick and dirty event handler pattern to enable the application to respond
// when the origin is changed.
#originWatchers = [];
// when the clusterUrl is changed.
#clusterUrlWatchers = [];
onOriginChange(fn) {
this.#originWatchers.push(fn);
onClusterUrlChange(fn) {
this.#clusterUrlWatchers.push(fn);
}
triggerOriginChanged() {
this.#originWatchers.forEach((fn) => fn(this.#origin));
triggerClusterUrlChanged() {
this.#clusterUrlWatchers.forEach((fn) => fn(this.#clusterUrl));
}
}
@@ -1,27 +1,12 @@
import { module, test } from 'qunit';
import {
visit,
// currentURL,
// fillIn,
// click,
find,
//findAll,
//getRootElement
//setupOnerror,
} from '@ember/test-helpers';
import { visit, find } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
// import { Response } from 'miragejs';
// import a11yAudit from 'ember-a11y-testing/test-support/audit';
import sinon from 'sinon';
import {
// currentSession,
// authenticateSession,
invalidateSession,
} from 'ember-simple-auth/test-support';
import { invalidateSession } from 'ember-simple-auth/test-support';
import { setupBrowserFakes } from 'ember-browser-services/test-support';
module('Acceptance | origin', function (hooks) {
module('Acceptance | index', function (hooks) {
setupApplicationTest(hooks);
setupBrowserFakes(hooks, { window: true });
setupMirage(hooks);
@@ -31,13 +16,13 @@ module('Acceptance | origin', function (hooks) {
};
const urls = {
origin: null,
clusterUrl: null,
};
hooks.beforeEach(function () {
invalidateSession();
urls.origin = '/origin';
urls.clusterUrl = '/cluster-url';
const ipcService = this.owner.lookup('service:ipc');
stubs.ipcService = sinon.stub(ipcService, 'invoke');
@@ -50,7 +35,7 @@ module('Acceptance | origin', function (hooks) {
test('visiting index with chrome disabled hides custom window actions', async function (assert) {
assert.expect(3);
stubs.ipcService.withArgs('showWindowActions').returns(false);
await visit(urls.origin);
await visit(urls.clusterUrl);
assert.notOk(find('.button-window-close'), 'Window close button');
assert.notOk(find('.button-window-minimize'), 'Window minimize button');
assert.notOk(find('.button-window-fullscreen'), 'Window fullscreen button');
@@ -59,7 +44,7 @@ module('Acceptance | origin', function (hooks) {
test('visiting index with chrome enabled shows custom window actions', async function (assert) {
assert.expect(3);
stubs.ipcService.withArgs('showWindowActions').returns(true);
await visit(urls.origin);
await visit(urls.clusterUrl);
assert.ok(find('.button-window-close'), 'Window close button');
assert.ok(find('.button-window-minimize'), 'Window minimize button');
assert.ok(find('.button-window-fullscreen'), 'Window fullscreen button');
@@ -68,7 +53,7 @@ module('Acceptance | origin', function (hooks) {
test('visiting index with MacOS chrome enabled', async function (assert) {
assert.expect(1);
stubs.ipcService.withArgs('hasMacOSChrome').returns(true);
await visit(urls.origin);
await visit(urls.clusterUrl);
assert.ok(
find('.rose-header.header-cushion'),
'Adds header padding around native window actions'
@@ -78,7 +63,7 @@ module('Acceptance | origin', function (hooks) {
test('visiting index with MacOS chrome disabled', async function (assert) {
assert.expect(1);
stubs.ipcService.withArgs('hasMacOSChrome').returns(false);
await visit(urls.origin);
await visit(urls.clusterUrl);
assert.notOk(
find('.rose-header.header-cushion'),
'Does not add header padding around native window actions'
@@ -5,9 +5,7 @@ import {
fillIn,
click,
find,
//findAll,
getRootElement,
//setupOnerror,
} from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
@@ -46,7 +44,7 @@ module('Acceptance | authentication', function (hooks) {
const urls = {
index: '/',
origin: '/origin',
clusterUrl: '/cluster-url',
scopes: {
global: null,
org: null,
@@ -61,10 +59,10 @@ module('Acceptance | authentication', function (hooks) {
sessions: null,
};
const setDefaultOrigin = (test) => {
const setDefaultClusterUrl = (test) => {
const windowOrigin = window.location.origin;
const origin = test.owner.lookup('service:origin');
origin.rendererOrigin = windowOrigin;
const clusterUrl = test.owner.lookup('service:clusterUrl');
clusterUrl.rendererClusterUrl = windowOrigin;
};
hooks.beforeEach(function () {
@@ -124,7 +122,7 @@ module('Acceptance | authentication', function (hooks) {
// Mock the postMessage interface used by IPC.
this.owner.register('service:browser/window', WindowMockIPC);
setDefaultOrigin(this);
setDefaultClusterUrl(this);
});
test('visiting index while unauthenticated redirects to global authenticate method', async function (assert) {
@@ -144,12 +142,12 @@ module('Acceptance | authentication', function (hooks) {
assert.ok(find('.rose-message'));
});
test('visiting authenticate route without origin redirects to origin index', async function (assert) {
test('visiting authenticate route without clusterUrl redirects to clusterUrl index', async function (assert) {
assert.expect(1);
this.owner.lookup('service:origin').rendererOrigin = null;
this.owner.lookup('service:clusterUrl').rendererClusterUrl = null;
await visit(urls.authenticate.global);
await a11yAudit();
assert.strictEqual(currentURL(), urls.origin);
assert.strictEqual(currentURL(), urls.clusterUrl);
});
test('visiting authenticate route when the scope cannot be loaded is allowed', async function (assert) {
@@ -172,11 +170,11 @@ module('Acceptance | authentication', function (hooks) {
assert.notOk(currentSession().isAuthenticated);
});
test('can reset origin before authentication', async function (assert) {
test('can reset clusterUrl before authentication', async function (assert) {
assert.expect(1);
await visit(urls.authenticate.methods.global);
await click('.change-origin a');
assert.strictEqual(currentURL(), urls.origin);
assert.strictEqual(currentURL(), urls.clusterUrl);
});
test('signing out redirects to first global authenticate method', async function (assert) {
@@ -1,29 +1,15 @@
import { module, test } from 'qunit';
import {
visit,
currentURL,
fillIn,
click,
find,
//findAll,
//getRootElement
//setupOnerror,
} from '@ember/test-helpers';
import { visit, currentURL, fillIn, click, find } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
// import { Response } from 'miragejs';
import a11yAudit from 'ember-a11y-testing/test-support/audit';
import sinon from 'sinon';
import {
// currentSession,
// authenticateSession,
invalidateSession,
} from 'ember-simple-auth/test-support';
import { invalidateSession } from 'ember-simple-auth/test-support';
import { setupBrowserFakes } from 'ember-browser-services/test-support';
import WindowMockIPC from '../helpers/window-mock-ipc';
import config from '../../config/environment';
module('Acceptance | origin', function (hooks) {
module('Acceptance | clusterUrl', function (hooks) {
setupApplicationTest(hooks);
setupBrowserFakes(hooks, { window: true });
setupMirage(hooks);
@@ -53,7 +39,7 @@ module('Acceptance | origin', function (hooks) {
const urls = {
index: '/',
origin: '/origin',
clusterUrl: '/cluster-url',
scopes: {
global: null,
org: null,
@@ -117,64 +103,63 @@ module('Acceptance | origin', function (hooks) {
test('visiting index', async function (assert) {
assert.expect(1);
await visit(urls.origin);
await visit(urls.clusterUrl);
await a11yAudit();
assert.strictEqual(currentURL(), urls.origin);
assert.strictEqual(currentURL(), urls.clusterUrl);
});
test('visiting index without an origin specified redirects to origin route', async function (assert) {
test('visiting index without a clusterUrl specified redirects to clusterUrl route', async function (assert) {
assert.expect(2);
await visit(urls.index);
await a11yAudit();
assert.notOk(mockIPC.origin);
assert.strictEqual(currentURL(), urls.origin);
assert.notOk(mockIPC.clusterUrl);
assert.strictEqual(currentURL(), urls.clusterUrl);
});
test('can set origin', async function (assert) {
test('can set clusterUrl', async function (assert) {
assert.expect(3);
assert.notOk(mockIPC.origin);
await visit(urls.origin);
assert.notOk(mockIPC.clusterUrl);
await visit(urls.clusterUrl);
await fillIn('[name="host"]', currentOrigin);
await click('[type="submit"]');
assert.strictEqual(currentURL(), urls.authenticate.methods.global);
assert.strictEqual(mockIPC.origin, currentOrigin);
assert.strictEqual(mockIPC.clusterUrl, currentOrigin);
});
test('can reset origin before authentication', async function (assert) {
test('can reset clusterUrl before authentication', async function (assert) {
assert.expect(4);
assert.notOk(mockIPC.origin);
await visit(urls.origin);
assert.notOk(mockIPC.clusterUrl);
await visit(urls.clusterUrl);
await fillIn('[name="host"]', currentOrigin);
await click('[type="submit"]');
assert.strictEqual(currentURL(), urls.authenticate.methods.global);
assert.strictEqual(mockIPC.origin, currentOrigin);
assert.strictEqual(mockIPC.clusterUrl, currentOrigin);
await click('.change-origin a');
assert.strictEqual(currentURL(), urls.origin);
assert.strictEqual(currentURL(), urls.clusterUrl);
});
test('captures error on origin update', async function (assert) {
test('captures error on clusterUrl update', async function (assert) {
assert.expect(2);
assert.notOk(mockIPC.origin);
sinon.stub(this.owner.lookup('service:origin'), 'setOrigin').throws();
await visit(urls.origin);
assert.notOk(mockIPC.clusterUrl);
sinon.stub(this.owner.lookup('service:clusterUrl'), 'setClusterUrl').throws();
await visit(urls.clusterUrl);
await fillIn('[name="host"]', currentOrigin);
await click('[type="submit"]');
assert.ok(find('.rose-notification.is-error'));
});
test('origin set automatically when autoOrigin is true', async function (assert) {
test('clusterUrl set automatically when autoOrigin is true', async function (assert) {
assert.expect(1);
config.autoOrigin = true;
await visit(urls.origin);
await visit(urls.clusterUrl);
assert.strictEqual(find('[name="host"]').value, currentOrigin);
config.autoOrigin = false;
});
test('origin is *not* set automatically when autoOrigin is false', async function (assert) {
test('clusterUrl is *not* set automatically when autoOrigin is false', async function (assert) {
assert.expect(2);
assert.notOk(config.autoOrigin, 'autoOrigin is disabled');
await visit(urls.origin);
await visit(urls.clusterUrl);
assert.notOk(find('[name="host"]').value, 'Origin field is empty');
});
});
+6 -16
View File
@@ -1,17 +1,7 @@
import { module, test } from 'qunit';
import {
visit,
currentURL,
//fillIn,
//click,
//find,
//findAll,
//getRootElement
//setupOnerror,
} from '@ember/test-helpers';
import { visit, currentURL } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
//import { Response } from 'miragejs';
import a11yAudit from 'ember-a11y-testing/test-support/audit';
import {
currentSession,
@@ -43,7 +33,7 @@ module('Acceptance | projects', function (hooks) {
const urls = {
index: '/',
origin: '/origin',
clusterUrl: '/cluster-url',
scopes: {
global: null,
org: null,
@@ -57,10 +47,10 @@ module('Acceptance | projects', function (hooks) {
projects: null,
};
const setDefaultOrigin = (test) => {
const setDefaultClusterUrl = (test) => {
const windowOrigin = window.location.origin;
const origin = test.owner.lookup('service:origin');
origin.rendererOrigin = windowOrigin;
const clusterUrl = test.owner.lookup('service:clusterUrl');
clusterUrl.rendererClusterUrl = windowOrigin;
};
hooks.beforeEach(function () {
@@ -103,7 +93,7 @@ module('Acceptance | projects', function (hooks) {
// Mock the postMessage interface used by IPC.
this.owner.register('service:browser/window', WindowMockIPC);
setDefaultOrigin(this);
setDefaultClusterUrl(this);
});
test('visiting index while unauthenticated redirects to global authenticate method', async function (assert) {
@@ -1,14 +1,5 @@
import { module, test } from 'qunit';
import {
visit,
currentURL,
//fillIn,
click,
find,
findAll,
//getRootElement
//setupOnerror,
} from '@ember/test-helpers';
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 { Response } from 'miragejs';
@@ -48,7 +39,7 @@ module('Acceptance | projects | sessions', function (hooks) {
const urls = {
index: '/',
origin: '/origin',
clusterUrl: '/cluster-url',
scopes: {
global: null,
org: null,
@@ -63,10 +54,10 @@ module('Acceptance | projects | sessions', function (hooks) {
sessions: null,
};
const setDefaultOrigin = (test) => {
const setDefaultClusterUrl = (test) => {
const windowOrigin = window.location.origin;
const origin = test.owner.lookup('service:origin');
origin.rendererOrigin = windowOrigin;
const clusterUrl = test.owner.lookup('service:clusterUrl');
clusterUrl.rendererClusterUrl = windowOrigin;
};
hooks.beforeEach(function () {
@@ -117,19 +108,19 @@ module('Acceptance | projects | sessions', function (hooks) {
urls.sessions = `${urls.projects}/sessions`;
class MockIPC {
origin = null;
clusterUrl = null;
invoke(method, payload) {
return this[method](payload);
}
getOrigin() {
return this.origin;
getClusterUrl() {
return this.clusterUrl;
}
setOrigin(origin) {
this.origin = origin;
return this.origin;
setClusterUrl(clusterUrl) {
this.clusterUrl = clusterUrl;
return this.clusterUrl;
}
}
@@ -144,7 +135,7 @@ module('Acceptance | projects | sessions', function (hooks) {
};
window.addEventListener('message', messageHandler);
setDefaultOrigin(this);
setDefaultClusterUrl(this);
const ipcService = this.owner.lookup('service:ipc');
stubs.ipcService = sinon.stub(ipcService, 'invoke');
@@ -1,14 +1,5 @@
import { module, test } from 'qunit';
import {
visit,
currentURL,
//fillIn,
click,
find,
findAll,
//getRootElement
//setupOnerror,
} from '@ember/test-helpers';
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 { Response } from 'miragejs';
@@ -48,7 +39,7 @@ module('Acceptance | projects | targets', function (hooks) {
const urls = {
index: '/',
origin: '/origin',
clusterUrl: '/cluster-url',
scopes: {
global: null,
org: null,
@@ -65,10 +56,10 @@ module('Acceptance | projects | targets', function (hooks) {
sessions: null,
};
const setDefaultOrigin = (test) => {
const setDefaultClusterUrl = (test) => {
const windowOrigin = window.location.origin;
const origin = test.owner.lookup('service:origin');
origin.rendererOrigin = windowOrigin;
const clusterUrl = test.owner.lookup('service:clusterUrl');
clusterUrl.rendererClusterUrl = windowOrigin;
};
hooks.beforeEach(function () {
@@ -124,19 +115,19 @@ module('Acceptance | projects | targets', function (hooks) {
urls.sessions = `${urls.target}/sessions`;
class MockIPC {
origin = null;
clusterUrl = null;
invoke(method, payload) {
return this[method](payload);
}
getOrigin() {
return this.origin;
getClusterUrl() {
return this.clusterUrl;
}
setOrigin(origin) {
this.origin = origin;
return this.origin;
setClusterUrl(clusterUrl) {
this.clusterUrl = clusterUrl;
return this.clusterUrl;
}
}
@@ -151,7 +142,7 @@ module('Acceptance | projects | targets', function (hooks) {
};
window.addEventListener('message', messageHandler);
setDefaultOrigin(this);
setDefaultClusterUrl(this);
const ipcService = this.owner.lookup('service:ipc');
stubs.ipcService = sinon.stub(ipcService, 'invoke');
@@ -308,8 +299,16 @@ module('Acceptance | projects | targets', function (hooks) {
assert.ok(find('.rose-dialog-error'), 'Error dialog');
const dialogButtons = findAll('.rose-dialog-footer button');
assert.strictEqual(dialogButtons.length, 2);
assert.strictEqual(dialogButtons[0].textContent.trim(), 'Retry', 'Can retry');
assert.strictEqual(dialogButtons[1].textContent.trim(), 'Cancel', 'Can cancel');
assert.strictEqual(
dialogButtons[0].textContent.trim(),
'Retry',
'Can retry'
);
assert.strictEqual(
dialogButtons[1].textContent.trim(),
'Cancel',
'Can cancel'
);
});
test('handles connect error', async function (assert) {
@@ -326,8 +325,16 @@ module('Acceptance | projects | targets', function (hooks) {
assert.ok(find('.rose-dialog-error'), 'Error dialog');
const dialogButtons = findAll('.rose-dialog-footer button');
assert.strictEqual(dialogButtons.length, 2);
assert.strictEqual(dialogButtons[0].textContent.trim(), 'Retry', 'Can retry');
assert.strictEqual(dialogButtons[1].textContent.trim(), 'Cancel', 'Can cancel');
assert.strictEqual(
dialogButtons[0].textContent.trim(),
'Retry',
'Can retry'
);
assert.strictEqual(
dialogButtons[1].textContent.trim(),
'Cancel',
'Can cancel'
);
});
test('can retry on error', async function (assert) {
@@ -1,18 +1,8 @@
import { module, test } from 'qunit';
import {
visit,
currentURL,
//fillIn,
click,
find,
findAll,
//getRootElement
//setupOnerror,
} from '@ember/test-helpers';
import { visit, currentURL, click, find, findAll } from '@ember/test-helpers';
import { run, later } from '@ember/runloop';
import { setupApplicationTest } from 'ember-qunit';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
// import { Response } from 'miragejs';
import a11yAudit from 'ember-a11y-testing/test-support/audit';
import sinon from 'sinon';
import {
@@ -50,7 +40,7 @@ module('Acceptance | projects | targets | hosts', function (hooks) {
const urls = {
index: '/',
origin: '/origin',
clusterUrl: '/cluster-url',
scopes: {
global: null,
org: null,
@@ -67,10 +57,10 @@ module('Acceptance | projects | targets | hosts', function (hooks) {
hosts: null,
};
const setDefaultOrigin = (test) => {
const setDefaultClusterUrl = (test) => {
const windowOrigin = window.location.origin;
const origin = test.owner.lookup('service:origin');
origin.rendererOrigin = windowOrigin;
const clusterUrl = test.owner.lookup('service:clusterUrl');
clusterUrl.rendererClusterUrl = windowOrigin;
};
hooks.beforeEach(function () {
@@ -125,19 +115,19 @@ module('Acceptance | projects | targets | hosts', function (hooks) {
urls.hosts = `${urls.target}/hosts`;
class MockIPC {
origin = null;
clusterUrl = null;
invoke(method, payload) {
return this[method](payload);
}
getOrigin() {
return this.origin;
getClusterUrl() {
return this.clusterUrl;
}
setOrigin(origin) {
this.origin = origin;
return this.origin;
setClusterUrl(clusterUrl) {
this.clusterUrl = clusterUrl;
return this.clusterUrl;
}
}
@@ -152,7 +142,7 @@ module('Acceptance | projects | targets | hosts', function (hooks) {
};
window.addEventListener('message', messageHandler);
setDefaultOrigin(this);
setDefaultClusterUrl(this);
const ipcService = this.owner.lookup('service:ipc');
stubs.ipcService = sinon.stub(ipcService, 'invoke');
@@ -248,8 +238,16 @@ module('Acceptance | projects | targets | hosts', function (hooks) {
assert.ok(find('.rose-dialog-error'), 'Error dialog');
const dialogButtons = findAll('.rose-dialog-footer button');
assert.strictEqual(dialogButtons.length, 2);
assert.strictEqual(dialogButtons[0].textContent.trim(), 'Retry', 'Can retry');
assert.strictEqual(dialogButtons[1].textContent.trim(), 'Cancel', 'Can cancel');
assert.strictEqual(
dialogButtons[0].textContent.trim(),
'Retry',
'Can retry'
);
assert.strictEqual(
dialogButtons[1].textContent.trim(),
'Cancel',
'Can cancel'
);
}, 750);
await visit(urls.hosts);
});
@@ -270,8 +268,16 @@ module('Acceptance | projects | targets | hosts', function (hooks) {
assert.ok(find('.rose-dialog-error'), 'Error dialog');
const dialogButtons = findAll('.rose-dialog-footer button');
assert.strictEqual(dialogButtons.length, 2);
assert.strictEqual(dialogButtons[0].textContent.trim(), 'Retry', 'Can retry');
assert.strictEqual(dialogButtons[1].textContent.trim(), 'Cancel', 'Can cancel');
assert.strictEqual(
dialogButtons[0].textContent.trim(),
'Retry',
'Can retry'
);
assert.strictEqual(
dialogButtons[1].textContent.trim(),
'Cancel',
'Can cancel'
);
}, 750);
await visit(urls.hosts);
});
@@ -1,14 +1,5 @@
import { module, test } from 'qunit';
import {
visit,
currentURL,
//fillIn,
click,
find,
findAll,
//getRootElement
//setupOnerror,
} from '@ember/test-helpers';
import { visit, currentURL, click, find, findAll } from '@ember/test-helpers';
import { run, later } from '@ember/runloop';
import { setupApplicationTest } from 'ember-qunit';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
@@ -50,7 +41,7 @@ module('Acceptance | projects | targets | sessions', function (hooks) {
const urls = {
index: '/',
origin: '/origin',
clusterUrl: '/cluster-url',
scopes: {
global: null,
org: null,
@@ -67,10 +58,10 @@ module('Acceptance | projects | targets | sessions', function (hooks) {
sessions: null,
};
const setDefaultOrigin = (test) => {
const setDefaultClusterUrl = (test) => {
const windowOrigin = window.location.origin;
const origin = test.owner.lookup('service:origin');
origin.rendererOrigin = windowOrigin;
const clusterUrl = test.owner.lookup('service:clusterUrl');
clusterUrl.rendererClusterUrl = windowOrigin;
};
hooks.beforeEach(function () {
@@ -130,19 +121,19 @@ module('Acceptance | projects | targets | sessions', function (hooks) {
urls.sessions = `${urls.target}/sessions`;
class MockIPC {
origin = null;
clusterUrl = null;
invoke(method, payload) {
return this[method](payload);
}
getOrigin() {
return this.origin;
getClusterUrl() {
return this.clusterUrl;
}
setOrigin(origin) {
this.origin = origin;
return this.origin;
setClusterUrl(clusterUrl) {
this.clusterUrl = clusterUrl;
return this.clusterUrl;
}
}
@@ -157,7 +148,7 @@ module('Acceptance | projects | targets | sessions', function (hooks) {
};
window.addEventListener('message', messageHandler);
setDefaultOrigin(this);
setDefaultClusterUrl(this);
const ipcService = this.owner.lookup('service:ipc');
stubs.ipcService = sinon.stub(ipcService, 'invoke');
@@ -349,8 +340,16 @@ module('Acceptance | projects | targets | sessions', function (hooks) {
assert.ok(find('.rose-dialog-error'), 'Error dialog');
const dialogButtons = findAll('.rose-dialog-footer button');
assert.strictEqual(dialogButtons.length, 2);
assert.strictEqual(dialogButtons[0].textContent.trim(), 'Retry', 'Can retry');
assert.strictEqual(dialogButtons[1].textContent.trim(), 'Cancel', 'Can cancel');
assert.strictEqual(
dialogButtons[0].textContent.trim(),
'Retry',
'Can retry'
);
assert.strictEqual(
dialogButtons[1].textContent.trim(),
'Cancel',
'Can cancel'
);
}, 750);
await visit(urls.sessions);
});
@@ -368,8 +367,16 @@ module('Acceptance | projects | targets | sessions', function (hooks) {
assert.ok(find('.rose-dialog-error'), 'Error dialog');
const dialogButtons = findAll('.rose-dialog-footer button');
assert.strictEqual(dialogButtons.length, 2);
assert.strictEqual(dialogButtons[0].textContent.trim(), 'Retry', 'Can retry');
assert.strictEqual(dialogButtons[1].textContent.trim(), 'Cancel', 'Can cancel');
assert.strictEqual(
dialogButtons[0].textContent.trim(),
'Retry',
'Can retry'
);
assert.strictEqual(
dialogButtons[1].textContent.trim(),
'Cancel',
'Can cancel'
);
}, 750);
await visit(urls.sessions);
});
+44 -28
View File
@@ -1,14 +1,5 @@
import { module, test } from 'qunit';
import {
visit,
currentURL,
//fillIn,
click,
find,
findAll,
//getRootElement
//setupOnerror,
} from '@ember/test-helpers';
import { visit, currentURL, click, find, findAll } from '@ember/test-helpers';
import { run, later } from '@ember/runloop';
import { setupApplicationTest } from 'ember-qunit';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
@@ -49,7 +40,7 @@ module('Acceptance | scopes', function (hooks) {
const urls = {
index: '/',
origin: '/origin',
clusterUrl: '/cluster-url',
scopes: {
global: null,
org: null,
@@ -71,10 +62,10 @@ module('Acceptance | scopes', function (hooks) {
targetSessions: null,
};
const setDefaultOrigin = (test) => {
const setDefaultClusterUrl = (test) => {
const windowOrigin = window.location.origin;
const origin = test.owner.lookup('service:origin');
origin.rendererOrigin = windowOrigin;
const clusterUrl = test.owner.lookup('service:clusterUrl');
clusterUrl.rendererClusterUrl = windowOrigin;
};
hooks.beforeEach(function () {
@@ -137,19 +128,19 @@ module('Acceptance | scopes', function (hooks) {
urls.targetSessions = `${urls.target}/sessions`;
class MockIPC {
origin = null;
clusterUrl = null;
invoke(method, payload) {
return this[method](payload);
}
getOrigin() {
return this.origin;
getClusterUrl() {
return this.clusterUrl;
}
setOrigin(origin) {
this.origin = origin;
return this.origin;
setClusterUrl(clusterUrl) {
this.clusterUrl = clusterUrl;
return this.clusterUrl;
}
}
@@ -164,7 +155,7 @@ module('Acceptance | scopes', function (hooks) {
};
window.addEventListener('message', messageHandler);
setDefaultOrigin(this);
setDefaultClusterUrl(this);
const ipcService = this.owner.lookup('service:ipc');
stubs.ipcService = sinon.stub(ipcService, 'invoke');
@@ -234,11 +225,20 @@ module('Acceptance | scopes', function (hooks) {
assert.expect(3);
await later(async () => run.cancelTimers(), 750);
await visit(urls.targets);
await later(async () => assert.strictEqual(currentURL(), urls.targets), 750);
await later(
async () => assert.strictEqual(currentURL(), urls.targets),
750
);
await click('.rose-header-nav .rose-dropdown a:nth-of-type(2)');
await later(async () => assert.strictEqual(currentURL(), urls.org2Targets), 750);
await later(
async () => assert.strictEqual(currentURL(), urls.org2Targets),
750
);
await click('.rose-header-nav .rose-dropdown a:nth-of-type(3)');
later(async () => assert.strictEqual(currentURL(), urls.globalTargets), 750);
later(
async () => assert.strictEqual(currentURL(), urls.globalTargets),
750
);
await click('.rose-header-nav .rose-dropdown a:nth-of-type(1)');
});
@@ -318,8 +318,16 @@ module('Acceptance | scopes', function (hooks) {
assert.ok(find('.rose-dialog-error'), 'Error dialog');
const dialogButtons = findAll('.rose-dialog-footer button');
assert.strictEqual(dialogButtons.length, 2);
assert.strictEqual(dialogButtons[0].textContent.trim(), 'Retry', 'Can retry');
assert.strictEqual(dialogButtons[1].textContent.trim(), 'Cancel', 'Can cancel');
assert.strictEqual(
dialogButtons[0].textContent.trim(),
'Retry',
'Can retry'
);
assert.strictEqual(
dialogButtons[1].textContent.trim(),
'Cancel',
'Can cancel'
);
}, 750);
await visit(urls.scopes.global);
});
@@ -340,8 +348,16 @@ module('Acceptance | scopes', function (hooks) {
assert.ok(find('.rose-dialog-error'), 'Error dialog');
const dialogButtons = findAll('.rose-dialog-footer button');
assert.strictEqual(dialogButtons.length, 2);
assert.strictEqual(dialogButtons[0].textContent.trim(), 'Retry', 'Can retry');
assert.strictEqual(dialogButtons[1].textContent.trim(), 'Cancel', 'Can cancel');
assert.strictEqual(
dialogButtons[0].textContent.trim(),
'Retry',
'Can retry'
);
assert.strictEqual(
dialogButtons[1].textContent.trim(),
'Cancel',
'Can cancel'
);
}, 750);
await visit(urls.targets);
});
+5 -15
View File
@@ -1,18 +1,8 @@
import { module, test } from 'qunit';
import {
visit,
currentURL,
//fillIn,
//click,
//find,
//findAll,
//getRootElement
//setupOnerror,
} from '@ember/test-helpers';
import { visit, currentURL } from '@ember/test-helpers';
import { run, later } from '@ember/runloop';
import { setupApplicationTest } from 'ember-qunit';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
// import { Response } from 'miragejs';
import a11yAudit from 'ember-a11y-testing/test-support/audit';
import {
currentSession,
@@ -57,10 +47,10 @@ module('Acceptance | targets', function (hooks) {
targets: null,
};
const setDefaultOrigin = (test) => {
const setDefaultClusterUrl = (test) => {
const windowOrigin = window.location.origin;
const origin = test.owner.lookup('service:origin');
origin.rendererOrigin = windowOrigin;
const clusterUrl = test.owner.lookup('service:clusterUrl');
clusterUrl.rendererClusterUrl = windowOrigin;
};
hooks.beforeEach(function () {
@@ -104,7 +94,7 @@ module('Acceptance | targets', function (hooks) {
// Mock the postMessage interface used by IPC.
this.owner.register('service:browser/window', WindowMockIPC);
setDefaultOrigin(this);
setDefaultClusterUrl(this);
});
test('visiting index while unauthenticated redirects to global authenticate method', async function (assert) {
+12 -12
View File
@@ -13,7 +13,7 @@ const executablePath = helpers.returnExecutablePath(
);
// Set login variables
const originValue = 'http://localhost:9200';
const clusterUrlValue = 'http://localhost:9200';
const loginUsername = 'admin';
const loginPassword = 'password';
@@ -37,15 +37,15 @@ test.describe('Authentication end to end test suite', async () => {
test('Authenticates using user and password method and deauthenticates ', async () => {
const boundaryWindow = await electronApp.firstWindow(); // The window that contains the app.
// Override local storage origin
// Override local storage cluster URL
await boundaryWindow.evaluate(() =>
window.localStorage.setItem('desktop:origin', null)
window.localStorage.setItem('desktop:clusterUrl', null)
);
// Perform login
await helpers.login(
boundaryWindow,
originValue,
clusterUrlValue,
loginUsername,
loginPassword
);
@@ -115,14 +115,14 @@ test.describe('Authentication end to end test suite', async () => {
test('Authenticates using user and wrong password, it can not authenticate', async () => {
const boundaryWindow = await electronApp.firstWindow(); // The window that contains the app.
// Override local storage origin
// Override local storage cluster URL
await boundaryWindow.evaluate(() =>
window.localStorage.setItem('desktop:origin', null)
window.localStorage.setItem('desktop:clusterUrl', null)
);
// Perform login
await helpers.login(
boundaryWindow,
originValue,
clusterUrlValue,
loginUsername,
'123456789'
);
@@ -158,15 +158,15 @@ test.describe('Authentication end to end test suite', async () => {
});
});
// Override local storage origin
// Override local storage cluster URL
await boundaryWindow.evaluate(() =>
window.localStorage.setItem('desktop:origin', null)
window.localStorage.setItem('desktop:clusterUrl', null)
);
const originValue = 'http://localhost:9200';
const clusterUrlValue = 'http://localhost:9200';
// Fill the origin input
// Fill the cluster URL input
await boundaryWindow.waitForSelector('[name=host]');
await boundaryWindow.fill('[name=host]', originValue);
await boundaryWindow.fill('[name=host]', clusterUrlValue);
// Click the submit button
// Due to an error with await boundaryWindow.click('button[type="submit"]'); we are using a workaround.
+4 -4
View File
@@ -13,7 +13,7 @@ const executablePath = helpers.returnExecutablePath(
);
// Set login variables
const originValue = 'http://localhost:9200';
const clusterUrlValue = 'http://localhost:9200';
const loginUsername = 'admin';
const loginPassword = 'password';
@@ -36,15 +36,15 @@ test.describe('Targets end to end test suite', async () => {
test('Connects to a target', async () => {
const boundaryWindow = await electronApp.firstWindow(); // The window that contains the app.
// Override local storage origin
// Override local storage cluster URL
await boundaryWindow.evaluate(() =>
window.localStorage.setItem('desktop:origin', null)
window.localStorage.setItem('desktop:clusterURL', null)
);
// Perform the login
await helpers.login(
boundaryWindow,
originValue,
clusterUrlValue,
loginUsername,
loginPassword
);
+5 -5
View File
@@ -56,16 +56,16 @@ exports.click = async (appWindow, selector) => {
/**
* Performs login on the app window provided with the credentials provided.
* @param {object} appWindow The electron window to perform the action.
* @param {string} origin URL origin to set.
* @param {string} clusterUrl Cluster URL to set.
* @param {string} username Username to login.
* @param {string} password Password to login.
*/
exports.login = async (appWindow, origin, username, password) => {
// Fill the origin input
exports.login = async (appWindow, clusterUrl, username, password) => {
// Fill the clusterUrl input
await appWindow.waitForSelector('[name=host]');
await appWindow.fill('[name=host]', origin);
await appWindow.fill('[name=host]', clusterUrl);
// Click the set origin submit button
// Click the set clusterUrl submit button
await appWindow.waitForSelector('button[type="submit"]');
await this.click(appWindow, 'button[type="submit"]');
+9 -9
View File
@@ -1,22 +1,22 @@
import Service from '@ember/service';
class MockIPC {
origin = null;
clusterUrl = null;
invoke(method, payload) {
return this[method](payload);
}
getOrigin() {
return this.origin;
getClusterUrl() {
return this.clusterUrl;
}
setOrigin(origin) {
this.origin = origin;
return this.origin;
setClusterUrl(clusterUrl) {
this.clusterUrl = clusterUrl;
return this.clusterUrl;
}
resetOrigin() {}
resetClusterUrl() {}
hasMacOSChrome() {}
showWindowActions() {}
}
@@ -57,8 +57,8 @@ export default class extends Service {
// =methods
postMessage(data, origin, ports) {
if (origin !== window.location.origin) return;
postMessage(data, clusterUrl, ports) {
if (clusterUrl !== window.location.origin) return;
const { method, payload } = data;
if (method) {
const response = this.mockIPC.invoke(method, payload);
@@ -1,11 +1,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Route | origin', function (hooks) {
module('Unit | Route | ClusterUrl', function (hooks) {
setupTest(hooks);
test('it exists', function (assert) {
let route = this.owner.lookup('route:origin');
let route = this.owner.lookup('route:cluster-url');
assert.ok(route);
});
});
@@ -0,0 +1,49 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import sinon from 'sinon';
module('Unit | Service | clusterUrl', function (hooks) {
setupTest(hooks);
let service, ipcService;
hooks.beforeEach(function () {
service = this.owner.lookup('service:clusterUrl');
ipcService = this.owner.lookup('service:ipc');
});
test('resets clusterUrl on error', async function (assert) {
assert.expect(4);
const ipcServiceStubbed = sinon.stub(ipcService, 'invoke');
await service.setClusterUrl(window.location.origin);
assert.strictEqual(service.rendererClusterUrl, window.location.origin);
assert.strictEqual(service.adapter.host, window.location.origin);
ipcServiceStubbed.withArgs('setClusterUrl').rejects();
service.setClusterUrl('invalid-origin').catch(() => {
assert.notOk(service.rendererClusterUrl);
assert.strictEqual(service.adapter.host, window.location.origin);
});
});
test('drops trailing slashes from clusterUrl on setClusterUrl', async function (assert) {
assert.expect(4);
sinon.stub(ipcService, 'invoke');
await service.setClusterUrl(`${window.location.origin}/`);
assert.strictEqual(service.rendererClusterUrl, window.location.origin);
assert.strictEqual(service.adapter.host, window.location.origin);
await service.setClusterUrl(`${window.location.origin}//////`);
assert.strictEqual(service.rendererClusterUrl, window.location.origin);
assert.strictEqual(service.adapter.host, window.location.origin);
});
test('trim spaces from clusterUrl on setClusterUrl', async function (assert) {
assert.expect(4);
sinon.stub(ipcService, 'invoke');
await service.setClusterUrl(` ${window.location.origin}/ `);
assert.strictEqual(service.rendererClusterUrl, window.location.origin);
assert.strictEqual(service.adapter.host, window.location.origin);
await service.setClusterUrl(` ${window.location.origin} `);
assert.strictEqual(service.rendererClusterUrl, window.location.origin);
assert.strictEqual(service.adapter.host, window.location.origin);
});
});
@@ -1,49 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import sinon from 'sinon';
module('Unit | Service | origin', function (hooks) {
setupTest(hooks);
let service, ipcService;
hooks.beforeEach(function () {
service = this.owner.lookup('service:origin');
ipcService = this.owner.lookup('service:ipc');
});
test('resets origin on error', async function (assert) {
assert.expect(4);
const ipcServiceStubbed = sinon.stub(ipcService, 'invoke');
await service.setOrigin(window.location.origin);
assert.strictEqual(service.rendererOrigin, window.location.origin);
assert.strictEqual(service.adapter.host, window.location.origin);
ipcServiceStubbed.withArgs('setOrigin').rejects();
service.setOrigin('invalid-origin').catch(() => {
assert.notOk(service.rendererOrigin);
assert.strictEqual(service.adapter.host, window.location.origin);
});
});
test('drops trailing slashes from origin on setOrigin', async function (assert) {
assert.expect(4);
sinon.stub(ipcService, 'invoke');
await service.setOrigin(`${window.location.origin}/`);
assert.strictEqual(service.rendererOrigin, window.location.origin);
assert.strictEqual(service.adapter.host, window.location.origin);
await service.setOrigin(`${window.location.origin}//////`);
assert.strictEqual(service.rendererOrigin, window.location.origin);
assert.strictEqual(service.adapter.host, window.location.origin);
});
test('trim spaces from origin on setOrigin', async function (assert) {
assert.expect(4);
sinon.stub(ipcService, 'invoke');
await service.setOrigin(` ${window.location.origin}/ `);
assert.strictEqual(service.rendererOrigin, window.location.origin);
assert.strictEqual(service.adapter.host, window.location.origin);
await service.setOrigin(` ${window.location.origin} `);
assert.strictEqual(service.rendererOrigin, window.location.origin);
assert.strictEqual(service.adapter.host, window.location.origin);
});
});