Merge pull request #95 from hashicorp/refactor-scopes-iam

Refactor Scopes - IAM updates
This commit is contained in:
Randall Morey authored and GitHub committed 2020-07-30 12:22:33 -04:00
commit b9b61aeef4
174 files changed
+1738 -453

No files matched your search

+1 -3
View File
@@ -7,7 +7,6 @@ import { inject as service } from '@ember/service';
* endpoint, while deauthentication occurs on a scope endpoint.
*/
export default class PasswordAuthenticator extends BasePasswordAuthenticator {
// =services
@service store;
@@ -24,7 +23,7 @@ export default class PasswordAuthenticator extends BasePasswordAuthenticator {
*/
buildAuthEndpointURL({
scope: { id: scopeID },
authMethod: { id: authMethodID }
authMethod: { id: authMethodID },
}) {
const adapter = this.store.adapterFor('application');
const options = { adapterOptions: { scopeID, method: 'authenticate' } };
@@ -43,5 +42,4 @@ export default class PasswordAuthenticator extends BasePasswordAuthenticator {
const options = { adapterOptions: { method: 'deauthenticate' } };
return adapter.buildURL('scope', scopeID, options, 'findRecord');
}
}
-2
View File
@@ -2,9 +2,7 @@ import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class ApplicationController extends Controller {
// =services
@service session;
}
@@ -8,5 +8,4 @@ export default class OrgsOrgGroupsGroupController extends Controller {
* @type {string}
*/
@alias('model.displayName') breadCrumb;
}
@@ -14,5 +14,4 @@ export default class OrgsOrgGroupsNewController extends Controller {
get breadCrumb() {
return this.intl.t('titles.new');
}
}
@@ -2,7 +2,6 @@ import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class OrgsOrgProjectsController extends Controller {
// =services
@service intl;
@@ -15,5 +14,4 @@ export default class OrgsOrgProjectsController extends Controller {
get breadCrumb() {
return this.intl.t('resources.projects');
}
}
@@ -2,7 +2,6 @@ import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class OrgsOrgProjectsNewController extends Controller {
// =services
@service intl;
@@ -15,5 +14,4 @@ export default class OrgsOrgProjectsNewController extends Controller {
get breadCrumb() {
return this.intl.t('titles.new');
}
}
@@ -2,12 +2,10 @@ import Controller from '@ember/controller';
import { alias } from '@ember/object/computed';
export default class OrgsOrgProjectsProjectController extends Controller {
// =attributes
/**
* @type {string}
*/
@alias('model.displayName') breadCrumb;
}
@@ -2,7 +2,6 @@ import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class OrgsOrgProjectsProjectHostCatalogsController extends Controller {
// =services
@service intl;
@@ -15,5 +14,4 @@ export default class OrgsOrgProjectsProjectHostCatalogsController extends Contro
get breadCrumb() {
return this.intl.t('resources.host-catalogs');
}
}
@@ -2,12 +2,10 @@ import Controller from '@ember/controller';
import { alias } from '@ember/object/computed';
export default class OrgsOrgProjectsProjectHostCatalogsHostCatalogController extends Controller {
// =attributes
/**
* @type {string}
*/
@alias('model.displayName') breadCrumb;
}
@@ -2,7 +2,6 @@ import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class OrgsOrgProjectsProjectHostCatalogsNewController extends Controller {
// =services
@service intl;
@@ -15,5 +14,4 @@ export default class OrgsOrgProjectsProjectHostCatalogsNewController extends Con
get breadCrumb() {
return this.intl.t('titles.new');
}
}
@@ -14,5 +14,4 @@ export default class OrgsOrgRolesController extends Controller {
get breadCrumb() {
return this.intl.t('resources.roles');
}
}
@@ -14,5 +14,4 @@ export default class OrgsOrgRolesNewController extends Controller {
get breadCrumb() {
return this.intl.t('titles.new');
}
}
@@ -8,5 +8,4 @@ export default class OrgsOrgRolesRoleController extends Controller {
* @type {string}
*/
@alias('model.displayName') breadCrumb;
}
@@ -14,5 +14,4 @@ export default class OrgsOrgUsersController extends Controller {
get breadCrumb() {
return this.intl.t('resources.users');
}
}
-2
View File
@@ -2,9 +2,7 @@ import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class ScopesScopeController extends Controller {
// =services
@service session;
}
@@ -0,0 +1,18 @@
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class ScopesScopeGroupsController extends Controller {
// =services
@service intl;
// =attributes
/**
* Translated groups breadcrumb
* @type {string}
*/
get breadCrumb() {
return this.intl.t('resources.groups');
}
}
@@ -0,0 +1,13 @@
import Controller from '@ember/controller';
export default class ScopesScopeGroupsGroupController extends Controller {
// =attributes
/**
* A group breadcrumb
* @type {string}
*/
get breadCrumb() {
return this.model.displayName;
}
}
@@ -0,0 +1,18 @@
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class ScopesScopeGroupsNewController extends Controller {
// =services
@service intl;
// =attributes
/**
* Translated new group breadcrumb
* @type {string}
*/
get breadCrumb() {
return this.intl.t('titles.new');
}
}
@@ -2,7 +2,6 @@ import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class ScopesScopeProjectsController extends Controller {
// =services
@service intl;
@@ -15,5 +14,4 @@ export default class ScopesScopeProjectsController extends Controller {
get breadCrumb() {
return this.intl.t('resources.projects');
}
}
@@ -2,7 +2,6 @@ import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class ScopesScopeProjectsNewController extends Controller {
// =services
@service intl;
@@ -15,5 +14,4 @@ export default class ScopesScopeProjectsNewController extends Controller {
get breadCrumb() {
return this.intl.t('titles.new');
}
}
@@ -1,7 +1,6 @@
import Controller from '@ember/controller';
export default class ScopesScopeProjectsProjectController extends Controller {
// =attributes
/**
@@ -10,5 +9,4 @@ export default class ScopesScopeProjectsProjectController extends Controller {
get breadCrumb() {
return this.model.displayName;
}
}
@@ -0,0 +1,18 @@
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class ScopesScopeRolesController extends Controller {
// =services
@service intl;
// =attributes
/**
* Translated roles breadcrumb
* @type {string}
*/
get breadCrumb() {
return this.intl.t('resources.roles');
}
}
@@ -0,0 +1,18 @@
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class ScopesScopeRolesNewController extends Controller {
// =services
@service intl;
// =attributes
/**
* Translated new role breadcrumb
* @type {string}
*/
get breadCrumb() {
return this.intl.t('titles.new');
}
}
@@ -0,0 +1,13 @@
import Controller from '@ember/controller';
export default class ScopesScopeRolesRoleController extends Controller {
// =attributes
/**
* A role breadcrumb
* @type {string}
*/
get breadCrumb() {
return this.model.displayName;
}
}
@@ -0,0 +1,18 @@
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class ScopesScopeUsersController extends Controller {
// =services
@service intl;
// =attributes
/**
* Translated users breadcrumb
* @type {string}
*/
get breadCrumb() {
return this.intl.t('resources.users');
}
}
@@ -0,0 +1,18 @@
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class ScopesScopeUsersNewController extends Controller {
// =services
@service intl;
// =attributes
/**
* Translated new user breadcrumb
* @type {string}
*/
get breadCrumb() {
return this.intl.t('titles.new');
}
}
@@ -0,0 +1,13 @@
import Controller from '@ember/controller';
export default class ScopesScopeUsersUserController extends Controller {
// =attributes
/**
* An user breadcrumb
* @type {string}
*/
get breadCrumb() {
return this.model.displayName;
}
}
+29 -14
View File
@@ -7,11 +7,22 @@ export default class Router extends EmberRouter {
}
Router.map(function () {
this.route('scopes', function() {
this.route('scope', { path: ':scope_id' }, function() {
this.route('authenticate', function() {
this.route('method', { path: ':auth_method_id'});
this.route('scopes', function () {
this.route('scope', { path: ':scope_id' }, function () {
this.route('authenticate', function () {
this.route('method', { path: ':auth_method_id' });
});
this.route('users', function () {
this.route('user', { path: ':user_id' }, function () {});
this.route('new');
});
this.route('groups', function () {
this.route('group', { path: ':group_id' }, function () {});
this.route('new');
});
this.route('roles', function () {
this.route('role', { path: ':role_id' }, function () {});
this.route('new');
});
this.route('projects', function() {
this.route('project', { path: ':project_id' }, function() {
@@ -28,27 +39,31 @@ Router.map(function () {
this.route('orgs', function () {
this.route('org', { path: ':org_id' }, function () {
this.route('projects', function () {
this.route('project', { path: ':project_id' }, function() {
this.route('host-catalogs', function() {
this.route('host-catalog', { path: ':host_catalog_id' }, function() {});
this.route('project', { path: ':project_id' }, function () {
this.route('host-catalogs', function () {
this.route(
'host-catalog',
{ path: ':host_catalog_id' },
function () {}
);
this.route('new');
});
});
this.route('new');
});
this.route('users', function() {
this.route('user', { path: ':user_id' }, function() {});
this.route('users', function () {
this.route('user', { path: ':user_id' }, function () {});
this.route('new');
});
this.route('roles', function() {
this.route('role', { path: ':role_id' }, function() {});
this.route('roles', function () {
this.route('role', { path: ':role_id' }, function () {});
this.route('new');
});
this.route('groups', function() {
this.route('group', { path: ':group_id' }, function() {});
this.route('groups', function () {
this.route('group', { path: ':group_id' }, function () {});
this.route('new');
});
});
-1
View File
@@ -12,7 +12,6 @@ import { later } from '@ember/runloop';
export default class ApplicationRoute extends Route.extend(
ApplicationRouteMixin
) {
// =services
@service session;
-2
View File
@@ -1,7 +1,6 @@
import Route from '@ember/routing/route';
export default class IndexRoute extends Route {
// =methods
/**
@@ -10,5 +9,4 @@ export default class IndexRoute extends Route {
redirect() {
this.transitionTo('scopes');
}
}
-2
View File
@@ -1,7 +1,6 @@
import Route from '@ember/routing/route';
export default class OrgsRoute extends Route {
// =methods
/**
@@ -11,5 +10,4 @@ export default class OrgsRoute extends Route {
model() {
return this.store.findAll('org');
}
}
@@ -1,4 +1,3 @@
import Route from '@ember/routing/route';
export default class OrgsOrgGroupsGroupIndexRoute extends Route {
}
export default class OrgsOrgGroupsGroupIndexRoute extends Route {}
@@ -1,3 +1,3 @@
import Route from '@ember/routing/route';
export default class OrgsOrgProjectsIndexRoute extends Route { }
export default class OrgsOrgProjectsIndexRoute extends Route {}
@@ -38,7 +38,7 @@ export default class OrgsOrgProjectsProjectRoute extends Route {
this.render('orgs/org/projects/project/_sidebar', {
into: 'orgs/org',
outlet: 'sidebar',
model: model
model: model,
});
super.renderTemplate(...arguments);
}
@@ -1,7 +1,6 @@
import Route from '@ember/routing/route';
export default class OrgsOrgProjectsProjectHostCatalogsRoute extends Route {
// =methods
/**
@@ -3,7 +3,6 @@ import { inject as service } from '@ember/service';
import { action } from '@ember/object';
export default class OrgsOrgProjectsProjectHostCatalogsHostCatalogRoute extends Route {
// =services
@service notify;
@@ -63,5 +62,4 @@ export default class OrgsOrgProjectsProjectHostCatalogsHostCatalogRoute extends
this.notify.error(error.message, { closeAfter: null });
}
}
}
@@ -1,4 +1,3 @@
import Route from '@ember/routing/route';
export default class OrgsOrgProjectsProjectHostCatalogsHostCatalogIndexRoute extends Route {
}
export default class OrgsOrgProjectsProjectHostCatalogsHostCatalogIndexRoute extends Route {}
@@ -1,4 +1,3 @@
import Route from '@ember/routing/route';
export default class OrgsOrgProjectsProjectHostCatalogsIndexRoute extends Route {
}
export default class OrgsOrgProjectsProjectHostCatalogsIndexRoute extends Route {}
@@ -39,7 +39,10 @@ export default class OrgsOrgProjectsProjectHostCatalogsNewRoute extends Route {
async save(hostCatalog) {
try {
await hostCatalog.save();
this.transitionTo('orgs.org.projects.project.host-catalogs.host-catalog', hostCatalog);
this.transitionTo(
'orgs.org.projects.project.host-catalogs.host-catalog',
hostCatalog
);
// TODO: replace with translated strings
this.notify.success('Host catalog created.');
} catch (error) {
@@ -1,4 +1,3 @@
import Route from '@ember/routing/route';
export default class OrgsOrgProjectsProjectIndexRoute extends Route {
}
export default class OrgsOrgProjectsProjectIndexRoute extends Route {}
-1
View File
@@ -10,5 +10,4 @@ export default class OrgsOrgRolesRoute extends Route {
model() {
return this.store.findAll('role');
}
}
+1 -2
View File
@@ -1,4 +1,3 @@
import Route from '@ember/routing/route';
export default class OrgsOrgUsersIndexRoute extends Route {
}
export default class OrgsOrgUsersIndexRoute extends Route {}
-2
View File
@@ -2,7 +2,6 @@ import Route from '@ember/routing/route';
import { A } from '@ember/array';
export default class ScopesRoute extends Route {
// =methods
/**
@@ -20,5 +19,4 @@ export default class ScopesRoute extends Route {
// expected to default to the global scope, thus returning org scopes.
return this.store.findAll('scope').catch(() => A([]));
}
}
+4 -4
View File
@@ -3,7 +3,6 @@ import { inject as service } from '@ember/service';
import { get } from '@ember/object';
export default class ScopesIndexRoute extends Route {
// =services
@service session;
@@ -17,13 +16,14 @@ export default class ScopesIndexRoute extends Route {
* @param {?ScopeModel} model.firstObject
*/
redirect({ firstObject }) {
const authenticatedScopeID =
get(this.session, 'data.authenticated.scope.id');
const authenticatedScopeID = get(
this.session,
'data.authenticated.scope.id'
);
if (authenticatedScopeID) {
this.transitionTo('scopes.scope', authenticatedScopeID);
} else if (firstObject) {
this.transitionTo('scopes.scope', firstObject.id);
}
}
}
+6 -8
View File
@@ -1,7 +1,6 @@
import Route from '@ember/routing/route';
export default class ScopesScopeRoute extends Route {
// =methods
/**
@@ -15,12 +14,11 @@ export default class ScopesScopeRoute extends Route {
* @return {Promise{ScopeModel}}
*/
model({ scope_id: id }) {
return this.store.findRecord('scope', id)
.catch(() => {
const maybeExistingScope = this.store.peekRecord('scope', id);
// TODO it's unclear if creating a temporary unsaved scope is reliable
// we may need to revert to a POJO.
return maybeExistingScope || this.store.createRecord('scope', { id });
});
return this.store.findRecord('scope', id).catch(() => {
const maybeExistingScope = this.store.peekRecord('scope', id);
// TODO it's unclear if creating a temporary unsaved scope is reliable
// we may need to revert to a POJO.
return maybeExistingScope || this.store.createRecord('scope', { id });
});
}
}
@@ -3,7 +3,6 @@ import { inject as service } from '@ember/service';
import { hash } from 'rsvp';
export default class ScopesScopeAuthenticateRoute extends Route {
// =services
@service session;
@@ -41,5 +40,4 @@ export default class ScopesScopeAuthenticateRoute extends Route {
this.transitionTo(this.routeIfAlreadyAuthenticated);
}
}
}
@@ -1,7 +1,6 @@
import Route from '@ember/routing/route';
export default class ScopesScopeAuthenticateIndexRoute extends Route {
// =methods
/**
@@ -16,5 +15,4 @@ export default class ScopesScopeAuthenticateIndexRoute extends Route {
this.transitionTo('scopes.scope.authenticate.method', firstAuthMethod);
}
}
}
@@ -3,7 +3,6 @@ import { inject as service } from '@ember/service';
import { action } from '@ember/object';
export default class ScopesScopeAuthenticateMethodRoute extends Route {
// =services
@service session;
@@ -62,5 +61,4 @@ export default class ScopesScopeAuthenticateMethodRoute extends Route {
this.notify.error(errorMessage, { closeAfter: null });
}
}
}
+70
View File
@@ -0,0 +1,70 @@
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
export default class ScopesScopeGroupsRoute extends Route {
// =services
@service intl;
@service notify;
// =methods
/**
* Load all groups under current scope
* @return {Promise[GroupModel]}
*/
async model() {
const { id: scopeID } = this.modelFor('scopes.scope');
return this.store.findAll('group', { adapterOptions: { scopeID } });
}
// =actions
/**
* Rollback changes on a group.
* @param {GroupModel} group
*/
@action
cancel(group) {
const { isNew } = group;
group.rollbackAttributes();
if (isNew) this.transitionTo('scopes.scope.groups');
}
/**
* Save a group in current scope.
* @param {GroupModel} group
*/
@action
async save(group) {
const { isNew } = group;
try {
await group.save();
this.refresh();
this.notify.success(
this.intl.t(isNew ? 'notify.create-success' : 'notify.save-success')
);
this.transitionTo('scopes.scope.groups.group', group);
} catch (error) {
//TODO: replace with translated strings
this.notify.error(error.message, { closeAfter: null });
}
}
/**
* Delete a group in current scope and redirect to index
* @param {GroupModel} group
*/
@action
async delete(group) {
try {
await group.destroyRecord();
this.refresh();
this.notify.success(this.intl.t('notify.delete-success'));
this.transitionTo('scopes.scope.groups');
} catch (error) {
//TODO: replace with translated strings
this.notify.error(error.message, { closeAfter: null });
}
}
}
@@ -0,0 +1,18 @@
import Route from '@ember/routing/route';
export default class ScopesScopeGroupsGroupRoute extends Route {
// =methods
/**
* Load a group in current scope.
* @param {object} params
* @param {string} params.group_id
* @return {groupModel}
*/
async model({ group_id }) {
const { id: scopeID } = this.modelFor('scopes.scope');
return this.store.findRecord('group', group_id, {
adapterOptions: { scopeID },
});
}
}
@@ -0,0 +1,3 @@
import Route from '@ember/routing/route';
export default class ScopesScopeGroupsGroupIndexRoute extends Route {}
@@ -0,0 +1,3 @@
import Route from '@ember/routing/route';
export default class ScopesScopeGroupsIndexRoute extends Route {}
@@ -0,0 +1,14 @@
import Route from '@ember/routing/route';
export default class ScopesScopeGroupsNewRoute extends Route {
// =methods
/**
* Creates a new unsaved group.
* @return {GroupModel}
*/
model() {
const scopeModel = this.modelFor('scopes.scope');
return this.store.createRecord('group', { scopeModel });
}
}
-2
View File
@@ -1,7 +1,6 @@
import Route from '@ember/routing/route';
export default class ScopesScopeIndexRoute extends Route {
// =methods
/**
@@ -10,5 +9,4 @@ export default class ScopesScopeIndexRoute extends Route {
redirect() {
this.transitionTo('scopes.scope.authenticate');
}
}
+6 -6
View File
@@ -3,9 +3,9 @@ import { inject as service } from '@ember/service';
import { action } from '@ember/object';
export default class ScopesScopeProjectsRoute extends Route {
// =services
@service intl;
@service notify;
@service session;
@@ -61,11 +61,13 @@ export default class ScopesScopeProjectsRoute extends Route {
*/
@action
async save(project) {
const { isNew } = project;
try {
await project.save();
this.refresh();
// TODO: replace with translated strings
this.notify.success('Save succeeded.');
this.notify.success(
this.intl.t(isNew ? 'notify.create-success' : 'notify.save-success')
);
this.transitionTo('scopes.scope.projects.project', project);
} catch (error) {
// TODO: replace with translated strings
@@ -82,13 +84,11 @@ export default class ScopesScopeProjectsRoute extends Route {
try {
await project.destroyRecord();
this.refresh();
this.notify.success('notify.delete-success');
this.transitionTo('scopes.scope.projects');
// TODO: replace with translated strings
this.notify.success('Deleted project succesfully.');
} catch (error) {
// TODO: replace with translated strings
this.notify.error(error.message, { closeAfter: null });
}
}
}
@@ -1,4 +1,3 @@
import Route from '@ember/routing/route';
export default class ScopesScopeProjectsIndexRoute extends Route {
}
export default class ScopesScopeProjectsIndexRoute extends Route {}
@@ -1,7 +1,6 @@
import Route from '@ember/routing/route';
export default class ScopesScopeProjectsNewRoute extends Route {
// =methods
/**
@@ -12,8 +11,7 @@ export default class ScopesScopeProjectsNewRoute extends Route {
const { id } = this.modelFor('scopes.scope');
return this.store.createRecord('scope', {
type: 'project',
scopeID: id
scopeID: id,
});
}
}
@@ -1,7 +1,6 @@
import Route from '@ember/routing/route';
export default class ScopesScopeProjectsProjectRoute extends Route {
// =methods
/**
@@ -28,5 +27,4 @@ export default class ScopesScopeProjectsProjectRoute extends Route {
});
super.renderTemplate(...arguments);
}
}
@@ -1,4 +1,3 @@
import Route from '@ember/routing/route';
export default class ScopesScopeProjectsProjectIndexRoute extends Route {
}
export default class ScopesScopeProjectsProjectIndexRoute extends Route {}
+70
View File
@@ -0,0 +1,70 @@
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
export default class ScopesScopeRolesRoute extends Route {
// =services
@service intl;
@service notify;
// =methods
/**
* Load all roles under current scope.
* @return {Promise{[RoleModel]}}
*/
async model() {
const { id: scopeID } = this.modelFor('scopes.scope');
return this.store.findAll('role', { adapterOptions: { scopeID } });
}
// =actions
/**
* Rollback changes on an role.
* @param {RoleModel} role
*/
@action
cancel(role) {
const { isNew } = role;
role.rollbackAttributes();
if (isNew) this.transitionTo('scopes.scope.roles');
}
/**
* Save an role in current scope.
* @param {RoleModel} role
*/
@action
async save(role) {
const { isNew } = role;
try {
await role.save();
this.refresh();
this.notify.success(
this.intl.t(isNew ? 'notify.create-success' : 'notify.save-success')
);
this.transitionTo('scopes.scope.roles.role', role);
} catch (error) {
// TODO: replace with translated strings
this.notify.error(error.message, { closeAfter: null });
}
}
/**
* Delete role in current scope and redirect to index.
* @param {RoleModel} role
*/
@action
async delete(role) {
try {
await role.destroyRecord();
this.refresh();
this.notify.success(this.intl.t('notify.delete-success'));
this.transitionTo('scopes.scope.roles');
} catch (error) {
// TODO: replace with translated strings
this.notify.error(error.message, { closeAfter: null });
}
}
}
@@ -0,0 +1,3 @@
import Route from '@ember/routing/route';
export default class ScopesScopeRolesIndexRoute extends Route {}
@@ -0,0 +1,14 @@
import Route from '@ember/routing/route';
export default class ScopesScopeRolesNewRoute extends Route {
// =methods
/**
* Creates a new unsaved role.
* @return {RoleModel}
*/
model() {
const scopeModel = this.modelFor('scopes.scope');
return this.store.createRecord('role', { scopeModel });
}
}
@@ -0,0 +1,18 @@
import Route from '@ember/routing/route';
export default class ScopesScopeRolesRoleRoute extends Route {
// =methods
/**
* Load a role in current scope.
* @param {object} params
* @param {string} params.role_id
* @return {RoleModel}
*/
async model({ role_id }) {
const { id: scopeID } = this.modelFor('scopes.scope');
return this.store.findRecord('role', role_id, {
adapterOptions: { scopeID },
});
}
}
@@ -0,0 +1,3 @@
import Route from '@ember/routing/route';
export default class ScopesScopeRolesRoleIndexRoute extends Route {}
+71
View File
@@ -0,0 +1,71 @@
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
export default class ScopesScopeUsersRoute extends Route {
// =services
@service intl;
@service notify;
// =methods
/**
* Load all users under current scope.
* @return {Promise{[UserModel]}}
*/
async model() {
const { id: scopeID } = this.modelFor('scopes.scope');
return this.store.findAll('user', { adapterOptions: { scopeID } });
}
// =actions
/**
* Rollback changes on an user.
* @param {UserModel} user
*/
@action
cancel(user) {
const { isNew } = user;
user.rollbackAttributes();
if (isNew) this.transitionTo('scopes.scope.users');
}
/**
* Save an user in current scope.
* @param {UserModel} user
* @param {Event} e
*/
@action
async save(user) {
const { isNew } = user;
try {
await user.save();
this.refresh();
this.notify.success(
this.intl.t(isNew ? 'notify.create-success' : 'notify.save-success')
);
this.transitionTo('scopes.scope.users.user', user);
} catch (error) {
// TODO: replace with translated strings
this.notify.error(error.message, { closeAfter: null });
}
}
/**
* Delete user in current scope and redirect to index.
* @param {UserModel} user
*/
@action
async delete(user) {
try {
await user.destroyRecord();
this.refresh();
this.notify.success(this.intl.t('notify.delete-success'));
this.transitionTo('scopes.scope.users');
} catch (error) {
// TODO: replace with translated strings
this.notify.error(error.message, { closeAfter: null });
}
}
}
@@ -0,0 +1,3 @@
import Route from '@ember/routing/route';
export default class ScopesScopeUsersIndexRoute extends Route {}
@@ -0,0 +1,14 @@
import Route from '@ember/routing/route';
export default class ScopesScopeUsersNewRoute extends Route {
// =methods
/**
* Creates a new unsaved user.
* @return {UserModel}
*/
model() {
const scopeModel = this.modelFor('scopes.scope');
return this.store.createRecord('user', { scopeModel });
}
}
@@ -0,0 +1,18 @@
import Route from '@ember/routing/route';
export default class ScopesScopeUsersUserRoute extends Route {
// =methods
/**
* Load a user in current scope.
* @param {object} params
* @param {string} params.user_id
* @return {UserModel}
*/
async model({ user_id }) {
const { id: scopeID } = this.modelFor('scopes.scope');
return this.store.findRecord('user', user_id, {
adapterOptions: { scopeID },
});
}
}
@@ -0,0 +1,3 @@
import Route from '@ember/routing/route';
export default class ScopesScopeUsersUserIndexRoute extends Route {}
@@ -4,7 +4,6 @@ import { get } from '@ember/object';
//import config from '../config/environment';
export default class ApplicationSessionStore extends LocalStorageSessionStore {
@service store;
/**
@@ -41,7 +40,6 @@ export default class ApplicationSessionStore extends LocalStorageSessionStore {
const authenticated = get(sessionData, 'authenticated');
if (scope && authenticated) authenticated.scope = scope;
}
}
// import CookieSessionStore from 'auth/session-stores/cookie';
+12
View File
@@ -7,6 +7,18 @@
{{t "resources.projects"}}
</nav.link>
</Rose::Nav::Sidebar>
<Rose::Nav::Sidebar @title={{t "titles.iam"}} as |nav|>
<nav.link @route="scopes.scope.users">
{{t "resources.users"}}
</nav.link>
<nav.link @route="scopes.scope.groups">
{{t "resources.groups"}}
</nav.link>
<nav.link @route="scopes.scope.roles">
{{t "resources.roles"}}
</nav.link>
</Rose::Nav::Sidebar>
{{outlet "sidebar"}}
@@ -0,0 +1,3 @@
{{title (t "resources.groups")}}
{{outlet}}
@@ -0,0 +1,3 @@
{{title @model.displayName}}
{{outlet}}
@@ -0,0 +1,35 @@
<Rose::Layout::Page as |page|>
<page.breadcrumbs>
<BreadCrumbs />
</page.breadcrumbs>
<page.header>
<h2>{{t "resources.group"}}</h2>
</page.header>
<page.navigation>
<Rose::Nav::Tabs as |nav|>
<nav.link @route='scopes.scope.groups.group'>
{{t 'titles.details'}}
</nav.link>
</Rose::Nav::Tabs>
</page.navigation>
<page.body>
<Form::Project
@model={{@model}}
@submit={{route-action "save" @model}}
@cancel={{route-action "cancel" @model}}
/>
<Rose::Separator />
<Rose::Button
@style="warning"
@disabled={{@model.canSave}}
{{on "click" (route-action "delete" @model)}}
>
{{t 'actions.delete'}}
</Rose::Button>
</page.body>
</Rose::Layout::Page>
@@ -0,0 +1,63 @@
<Rose::Layout::Page as |page|>
<page.breadcrumbs>
<BreadCrumbs />
</page.breadcrumbs>
<page.header>
<h2>{{t "resources.groups"}}</h2>
</page.header>
<page.actions>
{{#if @model}}
<Rose::LinkButton @route="scopes.scope.groups.new" @style="primary">{{t 'titles.new'}}</Rose::LinkButton>
{{/if}}
</page.actions>
<page.body>
{{#if @model}}
<Rose::Table as |table|>
<table.header as |header|>
<header.row as |row|>
<row.cell>{{t 'form.label.name'}}</row.cell>
<row.cell>{{t 'form.label.description'}}</row.cell>
</header.row>
</table.header>
<table.body as |body|>
{{#each @model as |group|}}
<body.row as |row|>
<row.cell>
<LinkTo
@route="scopes.scope.groups.group"
@model={{group}}
>
{{group.name}}
</LinkTo>
</row.cell>
<row.cell>{{group.description}}</row.cell>
</body.row>
{{/each}}
</table.body>
</Rose::Table>
{{else}}
<Rose::Layout::Centered>
<Rose::Message @title={{t 'titles.groups-welcome'}} as |message|>
<message.description>
{{t 'descriptions.groups-welcome'}}
</message.description>
<message.link @route="scopes.scope.groups.new">
<Rose::Icon @name="plus-circle-outline" />
{{t 'titles.new'}}
</message.link>
</Rose::Message>
</Rose::Layout::Centered>
{{/if}}
</page.body>
</Rose::Layout::Page>
@@ -0,0 +1,21 @@
{{title (t 'titles.new')}}
<Rose::Layout::Page as |page|>
<page.breadcrumbs>
<BreadCrumbs />
</page.breadcrumbs>
<page.header>
<h2>{{t "titles.new"}}</h2>
</page.header>
<page.body>
<Form::Group
@model={{@model}}
@submit={{route-action "save" @model}}
@cancel={{route-action "cancel" @model}}
/>
</page.body>
</Rose::Layout::Page>
@@ -0,0 +1,3 @@
{{title (t "resources.roles")}}
{{outlet}}
@@ -0,0 +1,63 @@
<Rose::Layout::Page as |page|>
<page.breadcrumbs>
<BreadCrumbs />
</page.breadcrumbs>
<page.header>
<h2>{{t "resources.roles"}}</h2>
</page.header>
<page.actions>
{{#if @model}}
<Rose::LinkButton @route="scopes.scope.roles.new" @style="primary">{{t 'titles.new'}}</Rose::LinkButton>
{{/if}}
</page.actions>
<page.body>
{{#if @model}}
<Rose::Table as |table|>
<table.header as |header|>
<header.row as |row|>
<row.cell>{{t 'form.label.name'}}</row.cell>
<row.cell>{{t 'form.label.description'}}</row.cell>
</header.row>
</table.header>
<table.body as |body|>
{{#each @model as |role|}}
<body.row as |row|>
<row.cell>
<LinkTo
@route="scopes.scope.roles.role"
@model={{role}}
>
{{role.displayName}}
</LinkTo>
</row.cell>
<row.cell>{{role.description}}</row.cell>
</body.row>
{{/each}}
</table.body>
</Rose::Table>
{{else}}
<Rose::Layout::Centered>
<Rose::Message @title={{t 'titles.roles-welcome'}} as |message|>
<message.description>
{{t 'descriptions.roles-welcome'}}
</message.description>
<message.link @route="scopes.scope.roles.new">
<Rose::Icon @name="plus-circle-outline" />
{{t 'titles.new'}}
</message.link>
</Rose::Message>
</Rose::Layout::Centered>
{{/if}}
</page.body>
</Rose::Layout::Page>
@@ -0,0 +1,19 @@
{{title (t 'titles.new')}}
<Rose::Layout::Page as |page|>
<page.breadcrumbs>
<BreadCrumbs />
</page.breadcrumbs>
<page.header>
<h2>{{t "titles.new"}}</h2>
</page.header>
<page.body>
<Form::Role
@model={{@model}}
@submit={{route-action "save" @model}}
@cancel={{route-action "cancel" @model}}
/>
</page.body>
</Rose::Layout::Page>
@@ -0,0 +1,3 @@
{{title @model.displayName}}
{{outlet}}
@@ -0,0 +1,27 @@
<Rose::Layout::Page as |page|>
<page.breadcrumbs>
<BreadCrumbs />
</page.breadcrumbs>
<page.header>
<h2>{{t "resources.role"}}</h2>
</page.header>
<page.body>
<Form::Role
@model={{@model}}
@submit={{route-action "save" @model}}
@cancel={{route-action "cancel" @model}}
/>
<Rose::Separator />
<Rose::Button
@style="warning"
@disabled={{@model.canSave}}
{{on "click" (route-action "delete" @model)}}
>
{{t 'actions.delete'}}
</Rose::Button>
</page.body>
</Rose::Layout::Page>
@@ -0,0 +1,3 @@
{{title (t "resources.users")}}
{{outlet}}
@@ -0,0 +1,63 @@
<Rose::Layout::Page as |page|>
<page.breadcrumbs>
<BreadCrumbs />
</page.breadcrumbs>
<page.header>
<h2>{{t "resources.users"}}</h2>
</page.header>
<page.actions>
{{#if @model}}
<Rose::LinkButton @route="scopes.scope.users.new" @style="primary">{{t 'titles.new'}}</Rose::LinkButton>
{{/if}}
</page.actions>
<page.body>
{{#if @model}}
<Rose::Table as |table|>
<table.header as |header|>
<header.row as |row|>
<row.cell>{{t 'form.label.name'}}</row.cell>
<row.cell>{{t 'form.label.description'}}</row.cell>
</header.row>
</table.header>
<table.body as |body|>
{{#each @model as |user|}}
<body.row as |row|>
<row.cell>
<LinkTo
@route="scopes.scope.users.user"
@model={{user}}
>
{{user.name}}
</LinkTo>
</row.cell>
<row.cell>{{user.description}}</row.cell>
</body.row>
{{/each}}
</table.body>
</Rose::Table>
{{else}}
<Rose::Layout::Centered>
<Rose::Message @title={{t 'titles.users-welcome'}} as |message|>
<message.description>
{{t 'descriptions.users-welcome'}}
</message.description>
<message.link @route="scopes.scope.users.new">
<Rose::Icon @name="plus-circle-outline" />
{{t 'titles.new'}}
</message.link>
</Rose::Message>
</Rose::Layout::Centered>
{{/if}}
</page.body>
</Rose::Layout::Page>
@@ -0,0 +1,21 @@
{{title (t 'titles.new')}}
<Rose::Layout::Page as |page|>
<page.breadcrumbs>
<BreadCrumbs />
</page.breadcrumbs>
<page.header>
<h2>{{t "titles.new"}}</h2>
</page.header>
<page.body>
<Form::User
@model={{@model}}
@submit={{route-action "save" @model}}
@cancel={{route-action "cancel" @model}}
/>
</page.body>
</Rose::Layout::Page>
@@ -0,0 +1,3 @@
{{title @model.displayName}}
{{outlet}}
@@ -0,0 +1,35 @@
<Rose::Layout::Page as |page|>
<page.breadcrumbs>
<BreadCrumbs />
</page.breadcrumbs>
<page.header>
<h2>{{t "resources.user"}}</h2>
</page.header>
<page.navigation>
<Rose::Nav::Tabs as |nav|>
<nav.link @route='scopes.scope.users.user'>
{{t 'titles.details'}}
</nav.link>
</Rose::Nav::Tabs>
</page.navigation>
<page.body>
<Form::Project
@model={{@model}}
@submit={{route-action "save" @model}}
@cancel={{route-action "cancel" @model}}
/>
<Rose::Separator />
<Rose::Button
@style="warning"
@disabled={{@model.canSave}}
{{on "click" (route-action "delete" @model)}}
>
{{t 'actions.delete'}}
</Rose::Button>
</page.body>
</Rose::Layout::Page>
+1 -1
View File
@@ -65,7 +65,7 @@ export default function() {
this.patch('/scopes/:scope_id/roles/:id');
this.del('/scopes/:scope_id/roles/:id');
// group
// IAM: Groups
this.get('/scopes/:scope_id/groups');
this.post('/scopes/:scope_id/groups');
this.get('/scopes/:scope_id/groups/:id');
+3 -3
View File
@@ -17,12 +17,12 @@ export default function(server) {
server.createList('auth-method', 3, { scope });
// User
server.createList('user', 5);
server.createList('user', 5, { scope });
// Role
server.createList('role', 5);
server.createList('role', 5, { scope });
// Groups
server.createList('group', 5);
server.createList('group', 5, { scope });
// Other resources
+17 -14
View File
@@ -9,7 +9,7 @@ import {
invalidateSession,
} from 'ember-simple-auth/test-support';
module('Acceptance | authentication', function(hooks) {
module('Acceptance | authentication', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
@@ -30,10 +30,14 @@ module('Acceptance | authentication', function(hooks) {
invalidateSession();
indexURL = '/';
globalScope = this.server.create('scope', { id: 'global' });
orgScope = this.server.create('scope', {
type: 'org',
scope: { id: globalScope.id, type: globalScope.type }
}, 'withChildren');
orgScope = this.server.create(
'scope',
{
type: 'org',
scope: { id: globalScope.id, type: globalScope.type },
},
'withChildren'
);
scope = { id: orgScope.id, type: orgScope.type };
authMethod = this.server.create('auth-method', { scope });
orgScopeID = orgScope.id;
@@ -45,14 +49,14 @@ module('Acceptance | authentication', function(hooks) {
projectsURL = `/scopes/${orgScopeID}/projects`;
});
test('visiting auth methods authenticate route redirects to first auth method', async function(assert) {
test('visiting auth methods authenticate route redirects to first auth method', async function (assert) {
assert.expect(1);
await visit(authenticateURL);
await a11yAudit();
assert.equal(currentURL(), authMethodAuthenticateURL);
});
test('visiting any authentication parent route while unauthenticated redirects to first authenticate method', async function(assert) {
test('visiting any authentication parent route while unauthenticated redirects to first authenticate method', async function (assert) {
assert.expect(3);
await visit(indexURL);
assert.equal(currentURL(), authMethodAuthenticateURL);
@@ -61,21 +65,21 @@ module('Acceptance | authentication', function(hooks) {
assert.notOk(currentSession().isAuthenticated);
});
test('visiting projects while unauthenticated redirects to first authenticate method', async function(assert) {
test('visiting projects while unauthenticated redirects to first authenticate method', async function (assert) {
assert.expect(2);
await visit(projectsURL);
assert.equal(currentURL(), authMethodAuthenticateURL);
assert.notOk(currentSession().isAuthenticated);
});
test('visiting auth method authenticate route', async function(assert) {
test('visiting auth method authenticate route', async function (assert) {
assert.expect(1);
await visit(authMethodAuthenticateURL);
await a11yAudit();
assert.equal(currentURL(), authMethodAuthenticateURL);
});
test('visiting any authentication parent route while already authenticated redirects to projects', async function(assert) {
test('visiting any authentication parent route while already authenticated redirects to projects', async function (assert) {
assert.expect(6);
authenticateSession({ scope });
await visit(indexURL);
@@ -91,7 +95,7 @@ module('Acceptance | authentication', function(hooks) {
assert.ok(currentSession().isAuthenticated);
});
test('failed authentication shows a notification message', async function(assert) {
test('failed authentication shows a notification message', async function (assert) {
assert.expect(3);
await visit(authMethodAuthenticateURL);
assert.notOk(currentSession().isAuthenticated);
@@ -101,7 +105,7 @@ module('Acceptance | authentication', function(hooks) {
assert.notOk(currentSession().isAuthenticated);
});
test('successful authentication redirects to projects', async function(assert) {
test('successful authentication redirects to projects', async function (assert) {
assert.expect(4);
await visit(authMethodAuthenticateURL);
assert.notOk(currentSession().isAuthenticated);
@@ -113,7 +117,7 @@ module('Acceptance | authentication', function(hooks) {
assert.ok(currentSession().isAuthenticated);
});
test('deauthentication redirects to first authenticate method', async function(assert) {
test('deauthentication redirects to first authenticate method', async function (assert) {
assert.expect(3);
await visit(authMethodAuthenticateURL);
await fillIn('[name="identification"]', 'test');
@@ -124,5 +128,4 @@ module('Acceptance | authentication', function(hooks) {
assert.notOk(currentSession().isAuthenticated);
assert.equal(currentURL(), authMethodAuthenticateURL);
});
});
+116 -38
View File
@@ -7,7 +7,8 @@ module('Acceptance | breadcrumbs', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
let org;
let orgScope;
let getProjectScope;
let project;
let hostCatalog;
let user;
@@ -22,142 +23,219 @@ module('Acceptance | breadcrumbs', function (hooks) {
let crumbPath;
hooks.beforeEach(function () {
org = this.server.create('org');
project = this.server.create('project');
user = this.server.create('user');
orgScope = this.server.create(
'scope',
{
type: 'org',
},
'withChildren'
);
hostCatalog = this.server.create('host-catalog');
getProjectScope = () =>
this.server.schema.scopes.where({ type: 'project' }).models[0];
project = getProjectScope();
user = this.server.create('user');
role = this.server.create('role');
group = this.server.create('group');
projectsURL = `/orgs/${org.id}/projects`;
projectsURL = `/scopes/${orgScope.id}/projects`;
newProjectURL = `${projectsURL}/new`;
projectURL = `${projectsURL}/${project.id}`;
hostCatalogsURL = `${projectURL}/host-catalogs`;
newHostCatalogURL = `${hostCatalogsURL}/new`;
hostCatalogURL = `${hostCatalogsURL}/${hostCatalog.id}`;
rolesURL = `/orgs/${org.id}/roles`;
rolesURL = `/scopes/${orgScope.id}/roles`;
newRoleURL = `${rolesURL}/new`;
roleURL = `${rolesURL}/${role.id}`;
groupsURL = `/orgs/${org.id}/groups`;
groupsURL = `/scopes/${orgScope.id}/groups`;
newGroupURL = `${groupsURL}/new`;
groupURL = `${groupsURL}/${group.id}`;
usersURL = `/orgs/${org.id}/users`;
usersURL = `/scopes/${orgScope.id}/users`;
newUserURL = `${usersURL}/${user.id}`;
userURL = `${usersURL}/new`;
// TODO: Update hostcatalog to scopes
hostCatalog = this.server.create('host-catalog');
hostCatalogsURL = `${projectURL}/host-catalogs`;
newHostCatalogURL = `${hostCatalogsURL}/new`;
hostCatalogURL = `${hostCatalogsURL}/${hostCatalog.id}`;
});
test('can navigate via breadcrumbs to projects from project', async function (assert) {
assert.expect(3);
await visit(projectURL);
assert.equal(currentURL(), projectURL, 'We begin on the expected page.');
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href).pathname;
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href)
.pathname;
assert.equal(crumbPath, projectURL, 'Last crumb has expected URL.');
await click(find('.rose-nav-breadcrumbs-link:first-child'));
assert.equal(currentURL(), projectsURL, 'After navigating via breadcrumbs, we are one level up.');
assert.equal(
currentURL(),
projectsURL,
'After navigating via breadcrumbs, we are one level up.'
);
});
test('can navigate via breadcrumbs to projects from new project', async function (assert) {
assert.expect(3);
await visit(newProjectURL);
assert.equal(currentURL(), newProjectURL, 'We begin on the expected page.');
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href).pathname;
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href)
.pathname;
assert.equal(crumbPath, newProjectURL, 'Last crumb has expected URL.');
await click(find('.rose-nav-breadcrumbs-link:first-child'));
assert.equal(currentURL(), projectsURL, 'After navigating via breadcrumbs, we are one level up.');
assert.equal(
currentURL(),
projectsURL,
'After navigating via breadcrumbs, we are one level up.'
);
});
test('can navigate via breadcrumbs to project from host catalogs', async function (assert) {
assert.expect(3);
await visit(hostCatalogsURL);
assert.equal(currentURL(), hostCatalogsURL, 'We begin on the expected page.');
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href).pathname;
assert.equal(
currentURL(),
hostCatalogsURL,
'We begin on the expected page.'
);
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href)
.pathname;
assert.equal(crumbPath, hostCatalogsURL, 'Last crumb has expected URL.');
await click(findAll('.rose-nav-breadcrumbs-link')[1]);
assert.equal(currentURL(), projectURL, 'After navigating via breadcrumbs, we are one level up.');
assert.equal(
currentURL(),
projectURL,
'After navigating via breadcrumbs, we are one level up.'
);
});
test('can navigate via breadcrumbs to host catalogs from host catalog', async function (assert) {
assert.expect(3);
await visit(hostCatalogURL);
assert.equal(currentURL(), hostCatalogURL, 'We begin on the expected page.');
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href).pathname;
assert.equal(
currentURL(),
hostCatalogURL,
'We begin on the expected page.'
);
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href)
.pathname;
assert.equal(crumbPath, hostCatalogURL, 'Last crumb has expected URL.');
await click(findAll('.rose-nav-breadcrumbs-link')[2]);
assert.equal(currentURL(), hostCatalogsURL, 'After navigating via breadcrumbs, we are one level up.');
assert.equal(
currentURL(),
hostCatalogsURL,
'After navigating via breadcrumbs, we are one level up.'
);
});
test('can navigate via breadcrumbs to host catalogs from new host catalog', async function (assert) {
assert.expect(3);
await visit(newHostCatalogURL);
assert.equal(currentURL(), newHostCatalogURL, 'We begin on the expected page.');
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href).pathname;
assert.equal(
currentURL(),
newHostCatalogURL,
'We begin on the expected page.'
);
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href)
.pathname;
assert.equal(crumbPath, newHostCatalogURL, 'Last crumb has expected URL.');
await click(findAll('.rose-nav-breadcrumbs-link')[2]);
assert.equal(currentURL(), hostCatalogsURL, 'After navigating via breadcrumbs, we are one level up.');
assert.equal(
currentURL(),
hostCatalogsURL,
'After navigating via breadcrumbs, we are one level up.'
);
});
test('can navigate via breadcrumbs to roles from role', async function (assert) {
assert.expect(3);
await visit(roleURL);
assert.equal(currentURL(), roleURL, 'We begin on the expected page.');
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href).pathname;
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href)
.pathname;
assert.equal(crumbPath, roleURL, 'Last crumb has expected URL.');
await click(find('.rose-nav-breadcrumbs-link:first-child'));
assert.equal(currentURL(), rolesURL, 'After navigating via breadcrumbs, we are one level up.');
assert.equal(
currentURL(),
rolesURL,
'After navigating via breadcrumbs, we are one level up.'
);
});
test('can navigate via breadcrumbs to roles from new role', async function (assert) {
assert.expect(3);
await visit(newRoleURL);
assert.equal(currentURL(), newRoleURL, 'We begin on the expected page.');
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href).pathname;
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href)
.pathname;
assert.equal(crumbPath, newRoleURL, 'Last crumb has expected URL.');
await click(find('.rose-nav-breadcrumbs-link:first-child'));
assert.equal(currentURL(), rolesURL, 'After navigating via breadcrumbs, we are one level up.');
assert.equal(
currentURL(),
rolesURL,
'After navigating via breadcrumbs, we are one level up.'
);
});
test('can navigate via breadcrumbs to groups from group', async function (assert) {
assert.expect(3);
await visit(groupURL);
assert.equal(currentURL(), groupURL, 'We begin on the expected page.');
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href).pathname;
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href)
.pathname;
assert.equal(crumbPath, groupURL, 'Last crumb has expected URL.');
await click(find('.rose-nav-breadcrumbs-link:first-child'));
assert.equal(currentURL(), groupsURL, 'After navigating via breadcrumbs, we are one level up.');
assert.equal(
currentURL(),
groupsURL,
'After navigating via breadcrumbs, we are one level up.'
);
});
test('can navigate via breadcrumbs to groups from new group', async function (assert) {
assert.expect(3);
await visit(newGroupURL);
assert.equal(currentURL(), newGroupURL, 'We begin on the expected page.');
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href).pathname;
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href)
.pathname;
assert.equal(crumbPath, newGroupURL, 'Last crumb has expected URL.');
await click(find('.rose-nav-breadcrumbs-link:first-child'));
assert.equal(currentURL(), groupsURL, 'After navigating via breadcrumbs, we are one level up.');
assert.equal(
currentURL(),
groupsURL,
'After navigating via breadcrumbs, we are one level up.'
);
});
test('can navigate via breadcrumbs to users from user', async function (assert) {
assert.expect(3);
await visit(userURL);
assert.equal(currentURL(), userURL, 'We begin on the expected page.');
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href).pathname;
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href)
.pathname;
assert.equal(crumbPath, userURL, 'Last crumb has expected URL.');
await click(find('.rose-nav-breadcrumbs-link:first-child'));
assert.equal(currentURL(), usersURL, 'After navigating via breadcrumbs, we are one level up.');
assert.equal(
currentURL(),
usersURL,
'After navigating via breadcrumbs, we are one level up.'
);
});
test('can navigate via breadcrumbs to users from new user', async function (assert) {
assert.expect(3);
await visit(newUserURL);
assert.equal(currentURL(), newUserURL, 'We begin on th expected page.');
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href).pathname;
crumbPath = new URL(find('.rose-nav-breadcrumbs-link:last-child').href)
.pathname;
assert.equal(crumbPath, newUserURL, 'Last crumb has expected URL.');
await click(find('.rose-nav-breadcrumbs-link:first-child'));
assert.equal(currentURL(), usersURL, 'After navigating via breadcrumbs, we are one level up.');
assert.equal(
currentURL(),
usersURL,
'After navigating via breadcrumbs, we are one level up.'
);
});
});
+67 -39
View File
@@ -4,47 +4,81 @@ 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 | groups', function(hooks) {
module('Acceptance | groups', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
let orgScope;
let groupsURL;
let groupURL;
let newGroupURL;
hooks.beforeEach(function () {
this.server.create('org');
orgScope = this.server.create(
'scope',
{
type: 'org',
},
'withChildren'
);
const group = this.server.create('group', {
scope: {
id: orgScope.id,
type: orgScope.type,
},
});
groupsURL = `/scopes/${orgScope.id}/groups`;
groupURL = `${groupsURL}/${group.id}`;
newGroupURL = `${groupsURL}/new`;
authenticateSession({});
});
test('visiting groups', async function (assert) {
assert.expect(1);
await visit('/orgs/1/groups');
await visit(groupsURL);
await a11yAudit();
assert.equal(currentURL(), '/orgs/1/groups');
assert.equal(currentURL(), groupsURL);
});
test('visiting a group', async function (assert) {
assert.expect(1);
await visit(newGroupURL);
await a11yAudit();
assert.equal(currentURL(), newGroupURL);
});
test('can create new group', async function (assert) {
assert.expect(4);
assert.equal(this.server.db.groups.length, 0);
await visit('/orgs/1/groups/new');
assert.expect(1);
const groupsCount = this.server.db.groups.length;
await visit(newGroupURL);
await fillIn('[name="name"]', 'group name');
await click('[type="submit"]');
assert.equal(currentURL(), '/orgs/1/groups/1');
assert.equal(this.server.db.groups.length, 1);
assert.equal(this.server.db.groups[0].name, 'group name');
assert.equal(this.server.db.groups.length, groupsCount + 1);
});
test('can cancel new group creation', async function (assert) {
assert.expect(3);
assert.equal(this.server.db.groups.length, 0);
await visit('/orgs/1/groups/new');
assert.expect(2);
const groupsCount = this.server.db.groups.length;
await visit(newGroupURL);
await fillIn('[name="name"]', 'group name');
await click('.rose-form-actions [type="button"]');
assert.equal(currentURL(), '/orgs/1/groups');
assert.equal(this.server.db.groups.length, 0);
assert.equal(currentURL(), groupsURL);
assert.equal(this.server.db.groups.length, groupsCount);
});
test('saving a new group with invalid fields displays error messages', async function (assert) {
assert.expect(2);
this.server.post('/orgs/:org_id/groups', () => {
this.server.post('/scopes/:scope_id/groups', () => {
return new Response(
400,
{},
@@ -63,7 +97,7 @@ module('Acceptance | groups', function(hooks) {
}
);
});
await visit('/orgs/1/groups/new');
await visit(newGroupURL);
await fillIn('[name="name"]', 'group name');
await click('[type="submit"]');
assert.ok(
@@ -80,36 +114,32 @@ module('Acceptance | groups', function(hooks) {
test('can save changes to an existing group', async function (assert) {
assert.expect(2);
this.server.createList('group', 1, {name: 'Admin group'});
await visit('/orgs/1/groups/1');
await visit(groupURL);
await fillIn('[name="name"]', 'Updated admin group');
await click('.rose-form-actions [type="submit"]');
assert.equal(currentURL(), '/orgs/1/groups/1');
assert.equal(currentURL(), groupURL);
assert.equal(this.server.db.groups[0].name, 'Updated admin group');
});
test('can cancel changes to an existing group', async function (assert) {
assert.expect(1);
this.server.createList('group', 1, {name: 'Admin group'});
await visit('/orgs/1/groups/1');
await visit(groupURL);
await fillIn('[name="name"]', 'Updated admin group');
await click('.rose-form-actions [type="button"]');
assert.equal(find('[name="name"]').value, 'Admin group');
assert.notEqual(find('[name="name"]').value, 'Updated admin group');
});
test('can delete a group', async function(assert) {
assert.expect(2);
this.server.createList('group', 1);
assert.equal(this.server.db.groups.length, 1);
await visit('/orgs/1/groups/1');
test('can delete a group', async function (assert) {
assert.expect(1);
const groupsCount = this.server.db.groups.length;
await visit(groupURL);
await click('.rose-button-warning');
assert.equal(this.server.db.groups.length, 0);
assert.equal(this.server.db.groups.length, groupsCount - 1);
});
test('saving an existing group with invalid fields displays error messages', async function (assert) {
assert.expect(2);
this.server.createList('group', 1);
this.server.patch('/orgs/:org_id/groups/:id', () => {
this.server.patch('/scopes/:scope_id/groups/:id', () => {
return new Response(
400,
{},
@@ -128,7 +158,7 @@ module('Acceptance | groups', function(hooks) {
}
);
});
await visit('/orgs/1/groups/1');
await visit(groupURL);
await fillIn('[name="name"]', 'random string');
await click('[type="submit"]');
assert.ok(
@@ -145,8 +175,7 @@ module('Acceptance | groups', function(hooks) {
test('errors are displayed when save project fails', async function (assert) {
assert.expect(1);
this.server.createList('group', 1);
this.server.patch('/orgs/:org_id/groups/:id', () => {
this.server.patch('/scopes/:scope_id/groups/:id', () => {
return new Response(
490,
{},
@@ -157,7 +186,7 @@ module('Acceptance | groups', function(hooks) {
}
);
});
await visit('/orgs/1/groups/1');
await visit(groupURL);
await fillIn('[name="name"]', 'Role name');
await click('[type="submit"]');
assert.ok(
@@ -169,8 +198,7 @@ module('Acceptance | groups', function(hooks) {
test('errors are displayed when delete project fails', async function (assert) {
assert.expect(1);
this.server.createList('group', 1);
this.server.del('/orgs/:org_id/groups/:id', () => {
this.server.del('/scopes/:scope_id/groups/:id', () => {
return new Response(
490,
{},
@@ -181,7 +209,7 @@ module('Acceptance | groups', function(hooks) {
}
);
});
await visit('/orgs/1/groups/1');
await visit(groupURL);
await click('.rose-button-warning');
assert.ok(
find('[role="alert"]').textContent.trim(),
@@ -11,7 +11,7 @@ import {
//invalidateSession,
} from 'ember-simple-auth/test-support';
module('Acceptance | host catalogs', function(hooks) {
module('Acceptance | host catalogs', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
@@ -65,7 +65,7 @@ module('Acceptance | host catalogs', function(hooks) {
assert.equal(currentURL(), urls.hostCatalogs);
});
test('can navigate to host catalog form', async function(assert) {
test('can navigate to host catalog form', async function (assert) {
assert.expect(1);
authenticateSession({});
await visit(urls.hostCatalogs);
@@ -74,7 +74,7 @@ module('Acceptance | host catalogs', function(hooks) {
assert.equal(currentURL(), urls.hostCatalog);
});
test('can delete host catalog', async function(assert) {
test('can delete host catalog', async function (assert) {
assert.expect(2);
const hostCatalogsCount = this.server.db.hostCatalogs.length;
authenticateSession({});
@@ -84,7 +84,7 @@ module('Acceptance | host catalogs', function(hooks) {
assert.equal(this.server.db.hostCatalogs.length, hostCatalogsCount - 1);
});
test('can update host catalog and save changes', async function(assert) {
test('can update host catalog and save changes', async function (assert) {
assert.expect(1);
authenticateSession({});
await visit(urls.hostCatalog);
@@ -93,7 +93,7 @@ module('Acceptance | host catalogs', function(hooks) {
assert.equal(this.server.db.hostCatalogs[0].name, 'Test Name');
});
test('can update host catalog and cancel changes', async function(assert) {
test('can update host catalog and cancel changes', async function (assert) {
assert.expect(1);
authenticateSession({});
await visit(urls.hostCatalog);
@@ -246,5 +246,4 @@ module('Acceptance | host catalogs', function(hooks) {
'Displays field-level errors.'
);
});
});
+11 -5
View File
@@ -20,9 +20,11 @@ module('Acceptance | projects', function (hooks) {
let initialProjectScopesCount;
hooks.beforeEach(function () {
org = this.server.create('scope', {type: 'org'}, 'withChildren');
getProjectScopesCount = () => this.server.schema.scopes.where({type: 'project'}).length;
getFirstProjectScope = () => this.server.schema.scopes.where({type: 'project'}).models[0];
org = this.server.create('scope', { type: 'org' }, 'withChildren');
getProjectScopesCount = () =>
this.server.schema.scopes.where({ type: 'project' }).length;
getFirstProjectScope = () =>
this.server.schema.scopes.where({ type: 'project' }).models[0];
initialProjectScopesCount = getProjectScopesCount();
orgID = org.id;
projectsURL = `/scopes/${orgID}/projects`;
@@ -44,7 +46,11 @@ module('Acceptance | projects', function (hooks) {
assert.notEqual(wrongProjectsURL, projectsURL);
await visit(wrongProjectsURL);
await a11yAudit();
assert.equal(currentURL(), projectsURL, 'Wrong projects path was redirected to correct path.');
assert.equal(
currentURL(),
projectsURL,
'Wrong projects path was redirected to correct path.'
);
});
test('can create new projects', async function (assert) {
@@ -119,7 +125,7 @@ module('Acceptance | projects', function (hooks) {
assert.equal(find('[name="name"]').value, existingProject.name);
});
test('can delete project', async function(assert) {
test('can delete project', async function (assert) {
assert.expect(1);
await visit(existingProjectURL);
await click('.rose-button-warning');
+66 -37
View File
@@ -4,46 +4,81 @@ 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 | roles', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
let orgScope;
let rolesURL;
let roleURL;
let newRoleURL;
hooks.beforeEach(function () {
this.server.create('org');
orgScope = this.server.create(
'scope',
{
type: 'org',
},
'withChildren'
);
const role = this.server.create('role', {
scope: {
id: orgScope.id,
type: orgScope.type,
},
});
rolesURL = `/scopes/${orgScope.id}/roles`;
roleURL = `${rolesURL}/${role.id}`;
newRoleURL = `${rolesURL}/new`;
authenticateSession({});
});
test('visiting roles', async function (assert) {
assert.expect(1);
await visit('/orgs/1/roles');
await visit(rolesURL);
await a11yAudit();
assert.equal(currentURL(), '/orgs/1/roles');
assert.equal(currentURL(), rolesURL);
});
test('visiting a role', async function (assert) {
assert.expect(1);
await visit(newRoleURL);
await a11yAudit();
assert.equal(currentURL(), newRoleURL);
});
test('can create new role', async function (assert) {
assert.expect(4);
assert.equal(this.server.db.roles.length, 0);
await visit('/orgs/1/roles/new');
assert.expect(1);
const rolesCount = this.server.db.roles.length;
await visit(newRoleURL);
await fillIn('[name="name"]', 'role name');
await click('[type="submit"]');
assert.equal(currentURL(), '/orgs/1/roles/1');
assert.equal(this.server.db.roles.length, 1);
assert.equal(this.server.db.roles[0].name, 'role name');
assert.equal(this.server.db.roles.length, rolesCount + 1);
});
test('can cancel new role creation', async function (assert) {
assert.expect(3);
assert.equal(this.server.db.roles.length, 0);
await visit('/orgs/1/roles/new');
assert.expect(2);
const rolesCount = this.server.db.roles.length;
await visit(newRoleURL);
await fillIn('[name="name"]', 'role name');
await click('.rose-form-actions [type="button"]');
assert.equal(currentURL(), '/orgs/1/roles');
assert.equal(this.server.db.roles.length, 0);
assert.equal(currentURL(), rolesURL);
assert.equal(this.server.db.roles.length, rolesCount);
});
test('saving a new role with invalid fields displays error messages', async function (assert) {
assert.expect(2);
this.server.post('/orgs/:org_id/roles', () => {
this.server.post('/scopes/:scope_id/roles', () => {
return new Response(
400,
{},
@@ -62,7 +97,7 @@ module('Acceptance | roles', function (hooks) {
}
);
});
await visit('/orgs/1/roles/new');
await visit(newRoleURL);
await fillIn('[name="name"]', 'role name');
await click('[type="submit"]');
assert.ok(
@@ -79,36 +114,32 @@ module('Acceptance | roles', function (hooks) {
test('can save changes to an existing role', async function (assert) {
assert.expect(2);
this.server.createList('role', 1, {name: 'Admin role'});
await visit('/orgs/1/roles/1');
await visit(roleURL);
await fillIn('[name="name"]', 'Updated admin role');
await click('.rose-form-actions [type="submit"]');
assert.equal(currentURL(), '/orgs/1/roles/1');
assert.equal(currentURL(), roleURL);
assert.equal(this.server.db.roles[0].name, 'Updated admin role');
});
test('can cancel changes to an existing role', async function (assert) {
assert.expect(1);
this.server.createList('role', 1, {name: 'Admin role'});
await visit('/orgs/1/roles/1');
await visit(roleURL);
await fillIn('[name="name"]', 'Updated admin role');
await click('.rose-form-actions [type="button"]');
assert.equal(find('[name="name"]').value, 'Admin role');
assert.notEqual(find('[name="name"]').value, 'Updated admin role');
});
test('can delete a role', async function(assert) {
assert.expect(2);
this.server.createList('role', 1);
assert.equal(this.server.db.roles.length, 1);
await visit('/orgs/1/roles/1');
test('can delete a role', async function (assert) {
assert.expect(1);
const rolesCount = this.server.db.roles.length;
await visit(roleURL);
await click('.rose-button-warning');
assert.equal(this.server.db.roles.length, 0);
assert.equal(this.server.db.roles.length, rolesCount - 1);
});
test('saving an existing role with invalid fields displays error messages', async function (assert) {
assert.expect(2);
this.server.createList('role', 1);
this.server.patch('/orgs/:org_id/roles/:id', () => {
this.server.patch('/scopes/:scope_id/roles/:id', () => {
return new Response(
400,
{},
@@ -127,7 +158,7 @@ module('Acceptance | roles', function (hooks) {
}
);
});
await visit('/orgs/1/roles/1');
await visit(roleURL);
await fillIn('[name="name"]', 'random string');
await click('[type="submit"]');
assert.ok(
@@ -144,8 +175,7 @@ module('Acceptance | roles', function (hooks) {
test('errors are displayed when save project fails', async function (assert) {
assert.expect(1);
this.server.createList('role', 1);
this.server.patch('/orgs/:org_id/roles/:id', () => {
this.server.patch('/scopes/:scope_id/roles/:id', () => {
return new Response(
490,
{},
@@ -156,7 +186,7 @@ module('Acceptance | roles', function (hooks) {
}
);
});
await visit('/orgs/1/roles/1');
await visit(roleURL);
await fillIn('[name="name"]', 'Role name');
await click('[type="submit"]');
assert.ok(
@@ -168,8 +198,7 @@ module('Acceptance | roles', function (hooks) {
test('errors are displayed when delete project fails', async function (assert) {
assert.expect(1);
this.server.createList('role', 1);
this.server.del('/orgs/:org_id/roles/:id', () => {
this.server.del('/scopes/:scope_id/roles/:id', () => {
return new Response(
490,
{},
@@ -180,7 +209,7 @@ module('Acceptance | roles', function (hooks) {
}
);
});
await visit('/orgs/1/roles/1');
await visit(roleURL);
await click('.rose-button-warning');
assert.ok(
find('[role="alert"]').textContent.trim(),
+67 -39
View File
@@ -4,47 +4,81 @@ 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 | users', function(hooks) {
module('Acceptance | users', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
let orgScope;
let usersURL;
let userURL;
let newUserURL;
hooks.beforeEach(function () {
this.server.create('org');
orgScope = this.server.create(
'scope',
{
type: 'org',
},
'withChildren'
);
const user = this.server.create('user', {
scope: {
id: orgScope.id,
type: orgScope.type,
},
});
usersURL = `/scopes/${orgScope.id}/users`;
userURL = `${usersURL}/${user.id}`;
newUserURL = `${usersURL}/new`;
authenticateSession({});
});
test('visiting users', async function (assert) {
assert.expect(1);
this.server.createList('user', 1);
await visit('/orgs/1/users');
await visit(usersURL);
await a11yAudit();
assert.equal(currentURL(), '/orgs/1/users');
assert.equal(currentURL(), usersURL);
});
test('visiting a user', async function (assert) {
assert.expect(1);
await visit(newUserURL);
await a11yAudit();
assert.equal(currentURL(), newUserURL);
});
test('can create new users', async function (assert) {
assert.expect(4);
assert.equal(this.server.db.users.length, 0);
await visit('/orgs/1/users/new');
assert.expect(1);
const usersCount = this.server.db.users.length;
await visit(newUserURL);
await fillIn('[name="name"]', 'User name');
await click('[type="submit"]');
assert.equal(currentURL(), '/orgs/1/users/1');
assert.equal(this.server.db.users.length, 1);
assert.equal(this.server.db.users[0].name, 'User name');
assert.equal(this.server.db.users.length, usersCount + 1);
});
test('can cancel creation of a new user', async function (assert) {
assert.expect(3);
assert.equal(this.server.db.users.length, 0);
await visit('/orgs/1/users/new');
assert.expect(2);
const usersCount = this.server.db.users.length;
await visit(newUserURL);
await fillIn('[name="name"]', 'User name');
await click('.rose-form-actions [type="button"]');
assert.equal(currentURL(), '/orgs/1/users');
assert.equal(this.server.db.users.length, 0);
assert.equal(currentURL(), usersURL);
assert.equal(this.server.db.users.length, usersCount);
});
test('saving a new user with invalid fields displays error messages', async function (assert) {
assert.expect(2);
this.server.post('/orgs/:org_id/users', () => {
this.server.post('scopes/:scope_id/users', () => {
return new Response(
400,
{},
@@ -63,7 +97,7 @@ module('Acceptance | users', function(hooks) {
}
);
});
await visit('/orgs/1/users/new');
await visit(newUserURL);
await fillIn('[name="name"]', 'User name');
await click('[type="submit"]');
assert.ok(
@@ -80,36 +114,32 @@ module('Acceptance | users', function(hooks) {
test('can save changes to an existing user', async function (assert) {
assert.expect(2);
this.server.createList('user', 1, {name: 'Test User'});
await visit('/orgs/1/users/1');
await visit(userURL);
await fillIn('[name="name"]', 'Updated user name');
await click('.rose-form-actions [type="submit"]');
assert.equal(currentURL(), '/orgs/1/users/1');
assert.equal(currentURL(), userURL);
assert.equal(this.server.db.users[0].name, 'Updated user name');
});
test('can cancel changes to an existing user', async function (assert) {
assert.expect(1);
this.server.createList('user', 1, {name: 'Test User'});
await visit('/orgs/1/users/1');
await visit(userURL);
await fillIn('[name="name"]', 'Unsaved user name');
await click('.rose-form-actions [type="button"]');
assert.equal(find('[name="name"]').value, 'Test User');
assert.notEqual(find('[name="name"]').value, 'Unsaved user name');
});
test('can delete an user', async function(assert) {
assert.expect(2);
this.server.createList('user', 1);
assert.equal(this.server.db.users.length, 1);
await visit('/orgs/1/users/1');
test('can delete an user', async function (assert) {
assert.expect(1);
const usersCount = this.server.db.users.length;
await visit(userURL);
await click('.rose-button-warning');
assert.equal(this.server.db.users.length, 0);
assert.equal(this.server.db.users.length, usersCount - 1);
});
test('saving an existing user with invalid fields displays error messages', async function (assert) {
assert.expect(2);
this.server.createList('user', 1);
this.server.patch('/orgs/:org_id/users/:id', () => {
this.server.patch('/scopes/:scope_id/users/:id', () => {
return new Response(
400,
{},
@@ -128,7 +158,7 @@ module('Acceptance | users', function(hooks) {
}
);
});
await visit('/orgs/1/users/1');
await visit(userURL);
await fillIn('[name="name"]', 'User name');
await click('[type="submit"]');
assert.ok(
@@ -145,8 +175,7 @@ module('Acceptance | users', function(hooks) {
test('errors are displayed when saving user fails', async function (assert) {
assert.expect(1);
this.server.createList('user', 1);
this.server.patch('/orgs/:org_id/users/:id', () => {
this.server.patch('/scopes/:scope_id/users/:id', () => {
return new Response(
490,
{},
@@ -157,7 +186,7 @@ module('Acceptance | users', function(hooks) {
}
);
});
await visit('/orgs/1/users/1');
await visit(userURL);
await fillIn('[name="name"]', 'User name');
await click('[type="submit"]');
assert.ok(
@@ -169,8 +198,7 @@ module('Acceptance | users', function(hooks) {
test('errors are displayed when user deletion fails', async function (assert) {
assert.expect(1);
this.server.createList('user', 1);
this.server.del('/orgs/:org_id/users/:id', () => {
this.server.del('/scopes/:scope_id/users/:id', () => {
return new Response(
490,
{},
@@ -181,7 +209,7 @@ module('Acceptance | users', function(hooks) {
}
);
});
await visit('/orgs/1/users/1');
await visit(userURL);
await click('.rose-button-warning');
assert.ok(
find('[role="alert"]').textContent.trim(),
@@ -3,11 +3,11 @@ import { setupRenderingTest } from 'ember-qunit';
import { render, find, findAll } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | bread-crumbs', function(hooks) {
module('Integration | Component | bread-crumbs', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
this.set('breadCrumbs', [{label: 'Level 1'}]);
test('it renders', async function (assert) {
this.set('breadCrumbs', [{ label: 'Level 1' }]);
await render(hbs`<BreadCrumbs @breadCrumbs={{this.breadCrumbs}} />`);
// Default index route
@@ -15,28 +15,34 @@ module('Integration | Component | bread-crumbs', function(hooks) {
assert.equal(find('.rose-nav-breadcrumbs').textContent.trim(), 'Level 1');
});
test('it renders with model', async function(assert) {
test('it renders with model', async function (assert) {
let store = this.owner.lookup('service:store');
let project = store.createRecord('project', {id: '1234'});
let project = store.createRecord('project', { id: '1234' });
this.set('breadCrumbs', [{
label: 'Level 2',
path: 'orgs.org.projects.project',
model: project
}]);
this.set('breadCrumbs', [
{
label: 'Level 2',
path: 'orgs.org.projects.project',
model: project,
},
]);
await render(hbs`<BreadCrumbs @breadCrumbs={{this.breadCrumbs}} />`);
assert.equal(find('.rose-nav-breadcrumbs').textContent.trim(), 'Level 2');
});
test('it renders multiple breadCrumbs', async function(assert) {
this.set('breadCrumbs', [{
label: 'Level 1'
},{
label: 'Level 2'
}, {
label: 'Level 3'
}]);
test('it renders multiple breadCrumbs', async function (assert) {
this.set('breadCrumbs', [
{
label: 'Level 1',
},
{
label: 'Level 2',
},
{
label: 'Level 3',
},
]);
await render(hbs`<BreadCrumbs @breadCrumbs={{this.breadCrumbs}} />`);
assert.equal(findAll('a').length, 3);
@@ -3,10 +3,10 @@ import { setupRenderingTest } from 'ember-qunit';
import { render, find } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | form/host-catalog', function(hooks) {
module('Integration | Component | form/host-catalog', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
this.submit = () => {};
@@ -1,11 +1,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Controller | application', function(hooks) {
module('Unit | Controller | application', function (hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
test('it exists', function (assert) {
let controller = this.owner.lookup('controller:application');
assert.ok(controller);
});
@@ -1,11 +1,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Controller | orgs/org/groups', function(hooks) {
module('Unit | Controller | orgs/org/groups', function (hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
test('it exists', function (assert) {
let controller = this.owner.lookup('controller:orgs/org/groups');
assert.ok(controller);
});
@@ -1,11 +1,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Controller | orgs/org/groups/group', function(hooks) {
module('Unit | Controller | orgs/org/groups/group', function (hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
test('it exists', function (assert) {
let controller = this.owner.lookup('controller:orgs/org/groups/group');
assert.ok(controller);
});
Loaded 100 of 174 files, more files were not shown because too many files have changed in this diff. Show more