parent
3ff2ba463a
commit
554446ae4e
|
@ -9,7 +9,17 @@ import DS from 'ember-data';
|
|||
|
||||
const { AdapterError } = DS;
|
||||
|
||||
const ENDPOINTS = ['health', 'seal-status', 'tokens', 'token', 'seal', 'unseal', 'init', 'capabilities-self'];
|
||||
const ENDPOINTS = [
|
||||
'health',
|
||||
'seal-status',
|
||||
'tokens',
|
||||
'token',
|
||||
'seal',
|
||||
'unseal',
|
||||
'init',
|
||||
'capabilities-self',
|
||||
'license',
|
||||
];
|
||||
|
||||
const REPLICATION_ENDPOINTS = {
|
||||
reindex: 'reindex',
|
||||
|
@ -28,6 +38,7 @@ export default ApplicationAdapter.extend({
|
|||
shouldBackgroundReloadRecord() {
|
||||
return true;
|
||||
},
|
||||
|
||||
findRecord(store, type, id, snapshot) {
|
||||
let fetches = {
|
||||
health: this.health(),
|
||||
|
@ -70,7 +81,7 @@ export default ApplicationAdapter.extend({
|
|||
},
|
||||
|
||||
features() {
|
||||
return this.ajax(`${this.buildURL()}/license/features`, 'GET', {
|
||||
return this.ajax(`${this.urlFor('license')}/features`, 'GET', {
|
||||
unauthenticated: true,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import ClusterAdapter from './cluster';
|
||||
|
||||
export default ClusterAdapter.extend({
|
||||
queryRecord() {
|
||||
return this._super(...arguments).then(resp => {
|
||||
resp.data.id = resp.data.license_id;
|
||||
return resp.data;
|
||||
});
|
||||
},
|
||||
|
||||
createRecord(store, type, snapshot) {
|
||||
let id = snapshot.attr('licenseId');
|
||||
return this._super(...arguments).then(() => {
|
||||
return {
|
||||
id,
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
updateRecord(store, type, snapshot) {
|
||||
let id = snapshot.attr('licenseId');
|
||||
return this._super(...arguments).then(() => {
|
||||
return {
|
||||
id,
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
pathForType() {
|
||||
return 'license';
|
||||
},
|
||||
|
||||
urlForUpdateRecord() {
|
||||
return this.buildURL() + '/license';
|
||||
},
|
||||
});
|
|
@ -76,7 +76,11 @@ export default ApplicationAdapter.extend({
|
|||
|
||||
saveZeroAddressConfig(store, type, snapshot) {
|
||||
const path = snapshot.id;
|
||||
const roles = store.peekAll('role-ssh').filterBy('zeroAddress').mapBy('id').join(',');
|
||||
const roles = store
|
||||
.peekAll('role-ssh')
|
||||
.filterBy('zeroAddress')
|
||||
.mapBy('id')
|
||||
.join(',');
|
||||
const url = `/v1/${path}/config/zeroaddress`;
|
||||
const data = { roles };
|
||||
if (roles === '') {
|
||||
|
|
|
@ -2,10 +2,13 @@ import { inject as service } from '@ember/service';
|
|||
import { or } from '@ember/object/computed';
|
||||
import Component from '@ember/component';
|
||||
import { run } from '@ember/runloop';
|
||||
import { computed } from '@ember/object';
|
||||
|
||||
export default Component.extend({
|
||||
auth: service(),
|
||||
wizard: service(),
|
||||
router: service(),
|
||||
version: service(),
|
||||
|
||||
transitionToRoute: function() {
|
||||
this.get('router').transitionTo(...arguments);
|
||||
|
@ -15,6 +18,8 @@ export default Component.extend({
|
|||
|
||||
isRenewing: or('fakeRenew', 'auth.isRenewing'),
|
||||
|
||||
isOSS: computed.alias('version.isOSS'),
|
||||
|
||||
actions: {
|
||||
restartGuide() {
|
||||
this.get('wizard').restartGuide();
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import Component from '@ember/component';
|
||||
import { allFeatures } from 'vault/helpers/all-features';
|
||||
import { computed } from '@ember/object';
|
||||
|
||||
export default Component.extend({
|
||||
expirationTime: '',
|
||||
startTime: '',
|
||||
licenseId: '',
|
||||
features: null,
|
||||
text: '',
|
||||
showForm: false,
|
||||
isTemporary: computed('licenseId', function() {
|
||||
return this.licenseId === 'temporary';
|
||||
}),
|
||||
featuresInfo: computed('features', function() {
|
||||
let info = [];
|
||||
allFeatures().forEach(feature => {
|
||||
let active = this.features.includes(feature) ? true : false;
|
||||
info.push({ name: feature, active: active });
|
||||
});
|
||||
return info;
|
||||
}),
|
||||
saveModel() {},
|
||||
actions: {
|
||||
saveModel(text) {
|
||||
this.saveModel(text);
|
||||
},
|
||||
toggleForm() {
|
||||
this.toggleProperty('showForm');
|
||||
},
|
||||
},
|
||||
});
|
|
@ -8,7 +8,9 @@ export default Component.extend({
|
|||
if (num) {
|
||||
num = parseInt(num, 10);
|
||||
}
|
||||
return Array(num || 0).fill(null).map(() => ({ value: '' }));
|
||||
return Array(num || 0)
|
||||
.fill(null)
|
||||
.map(() => ({ value: '' }));
|
||||
}),
|
||||
listLength: 0,
|
||||
actions: {
|
||||
|
|
|
@ -62,8 +62,7 @@ export default Controller.extend({
|
|||
const adapter = this.get('store').adapterFor('lease');
|
||||
const method = isForce ? 'forceRevokePrefix' : 'revokePrefix';
|
||||
const fn = adapter[method];
|
||||
fn
|
||||
.call(adapter, prefix)
|
||||
fn.call(adapter, prefix)
|
||||
.then(() => {
|
||||
return this.transitionToRoute('vault.cluster.access.leases.list-root').then(() => {
|
||||
this.get('flashMessages').success(`All of the leases under ${prefix} will be revoked.`);
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import Controller from '@ember/controller';
|
||||
|
||||
export default Controller.extend({
|
||||
licenseSuccess() {
|
||||
this.send('doRefresh');
|
||||
},
|
||||
licenseError() {
|
||||
//eat the error (handled in MessageError component)
|
||||
},
|
||||
actions: {
|
||||
saveModel({ text }) {
|
||||
this.model.save({ text }).then(() => this.licenseSuccess(), () => this.licenseError());
|
||||
},
|
||||
},
|
||||
});
|
|
@ -35,13 +35,15 @@ export default Controller.extend({
|
|||
modelMethod
|
||||
.call(config)
|
||||
.then(() => {
|
||||
this.transitionToRoute(...redirectArgs).followRedirects().then(() => {
|
||||
flash.success(
|
||||
`The performance mount filter config for the secondary ${id} was successfully ${isDelete
|
||||
? 'deleted'
|
||||
: 'saved'}.`
|
||||
);
|
||||
});
|
||||
this.transitionToRoute(...redirectArgs)
|
||||
.followRedirects()
|
||||
.then(() => {
|
||||
flash.success(
|
||||
`The performance mount filter config for the secondary ${id} was successfully ${
|
||||
isDelete ? 'deleted' : 'saved'
|
||||
}.`
|
||||
);
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
const errString = e.errors.join('.');
|
||||
|
|
|
@ -6,11 +6,14 @@ export default Controller.extend({
|
|||
|
||||
actions: {
|
||||
seal() {
|
||||
return this.model.cluster.store.adapterFor('cluster').seal().then(() => {
|
||||
this.model.cluster.get('leaderNode').set('sealed', true);
|
||||
this.get('auth').deleteCurrentToken();
|
||||
return this.transitionToRoute('vault.cluster');
|
||||
});
|
||||
return this.model.cluster.store
|
||||
.adapterFor('cluster')
|
||||
.seal()
|
||||
.then(() => {
|
||||
this.model.cluster.get('leaderNode').set('sealed', true);
|
||||
this.get('auth').deleteCurrentToken();
|
||||
return this.transitionToRoute('vault.cluster');
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -6,10 +6,12 @@ export default Controller.extend({
|
|||
|
||||
actions: {
|
||||
transitionToCluster(resp) {
|
||||
return this.get('model').reload().then(() => {
|
||||
this.get('wizard').transitionTutorialMachine(this.get('wizard.currentState'), 'CONTINUE', resp);
|
||||
return this.transitionToRoute('vault.cluster', this.get('model.name'));
|
||||
});
|
||||
return this.get('model')
|
||||
.reload()
|
||||
.then(() => {
|
||||
this.get('wizard').transitionTutorialMachine(this.get('wizard.currentState'), 'CONTINUE', resp);
|
||||
return this.transitionToRoute('vault.cluster', this.get('model.name'));
|
||||
});
|
||||
},
|
||||
|
||||
setUnsealState(resp) {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import { helper as buildHelper } from '@ember/component/helper';
|
||||
|
||||
const ALL_FEATURES = [
|
||||
'HSM',
|
||||
'Performance Replication',
|
||||
'DR Replication',
|
||||
'MFA',
|
||||
'Sentinel',
|
||||
'AWS KMS Autounseal',
|
||||
'GCP CKMS Autounseal',
|
||||
'Seal Wrapping',
|
||||
'Control Groups',
|
||||
'Azure Key Vault Seal',
|
||||
'Performance Standby',
|
||||
'Namespaces',
|
||||
];
|
||||
|
||||
export function allFeatures() {
|
||||
return ALL_FEATURES;
|
||||
}
|
||||
|
||||
export default buildHelper(allFeatures);
|
|
@ -0,0 +1,29 @@
|
|||
import DS from 'ember-data';
|
||||
const { attr } = DS;
|
||||
|
||||
/* sample response
|
||||
{
|
||||
"data": {
|
||||
"expiration_time": "2017-11-14T16:34:36.546753-05:00",
|
||||
"features": [
|
||||
"UI",
|
||||
"HSM",
|
||||
"Performance Replication",
|
||||
"DR Replication"
|
||||
],
|
||||
"license_id": "temporary",
|
||||
"start_time": "2017-11-14T16:04:36.546753-05:00"
|
||||
},
|
||||
"warnings": [
|
||||
"time left on license is 29m33s"
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
export default DS.Model.extend({
|
||||
expirationTime: attr('string'),
|
||||
features: attr('array'),
|
||||
licenseId: attr('string'),
|
||||
startTime: attr('string'),
|
||||
text: attr('string'),
|
||||
});
|
|
@ -12,6 +12,7 @@ Router.map(function() {
|
|||
this.route('auth');
|
||||
this.route('init');
|
||||
this.route('logout');
|
||||
this.route('license');
|
||||
this.route('settings', function() {
|
||||
this.route('index', { path: '/' });
|
||||
this.route('seal');
|
||||
|
|
|
@ -6,9 +6,11 @@ export default Route.extend(UnloadModel, {
|
|||
version: service(),
|
||||
|
||||
beforeModel() {
|
||||
return this.get('version').fetchFeatures().then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
return this.get('version')
|
||||
.fetchFeatures()
|
||||
.then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
},
|
||||
|
||||
model(params) {
|
||||
|
|
|
@ -6,9 +6,11 @@ export default Route.extend(UnloadModel, {
|
|||
version: service(),
|
||||
|
||||
beforeModel() {
|
||||
return this.get('version').fetchFeatures().then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
return this.get('version')
|
||||
.fetchFeatures()
|
||||
.then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
},
|
||||
|
||||
model() {
|
||||
|
|
|
@ -5,9 +5,11 @@ import UnloadModel from 'vault/mixins/unload-model-route';
|
|||
export default Route.extend(UnloadModel, {
|
||||
version: service(),
|
||||
beforeModel() {
|
||||
return this.get('version').fetchFeatures().then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
return this.get('version')
|
||||
.fetchFeatures()
|
||||
.then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
},
|
||||
model() {
|
||||
return this.get('version.hasNamespaces') ? this.store.createRecord('namespace') : null;
|
||||
|
|
|
@ -6,9 +6,11 @@ export default Route.extend(UnloadModel, {
|
|||
version: service(),
|
||||
beforeModel() {
|
||||
this.store.unloadAll('namespace');
|
||||
return this.get('version').fetchFeatures().then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
return this.get('version')
|
||||
.fetchFeatures()
|
||||
.then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
},
|
||||
model() {
|
||||
return this.get('version.hasNamespaces')
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import Route from '@ember/routing/route';
|
||||
import ClusterRoute from 'vault/mixins/cluster-route';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default Route.extend(ClusterRoute, {
|
||||
version: service(),
|
||||
beforeModel() {
|
||||
if (this.version.isOSS) {
|
||||
this.transitionTo('vault.cluster');
|
||||
}
|
||||
},
|
||||
|
||||
model() {
|
||||
return this.store.queryRecord('license', {});
|
||||
},
|
||||
|
||||
actions: {
|
||||
doRefresh() {
|
||||
this.refresh();
|
||||
},
|
||||
},
|
||||
});
|
|
@ -8,9 +8,11 @@ export default Route.extend(ClusterRoute, {
|
|||
version: service(),
|
||||
|
||||
beforeModel() {
|
||||
return this.get('version').fetchFeatures().then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
return this.get('version')
|
||||
.fetchFeatures()
|
||||
.then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
},
|
||||
|
||||
model(params) {
|
||||
|
|
|
@ -7,9 +7,11 @@ const ALLOWED_TYPES = ['acl', 'egp', 'rgp'];
|
|||
export default Route.extend(ClusterRoute, {
|
||||
version: service(),
|
||||
beforeModel() {
|
||||
return this.get('version').fetchFeatures().then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
return this.get('version')
|
||||
.fetchFeatures()
|
||||
.then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
},
|
||||
model(params) {
|
||||
let policyType = params.type;
|
||||
|
|
|
@ -8,9 +8,11 @@ export default Route.extend(ClusterRoute, {
|
|||
version: service(),
|
||||
|
||||
beforeModel() {
|
||||
return this.get('version').fetchFeatures().then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
return this.get('version')
|
||||
.fetchFeatures()
|
||||
.then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
},
|
||||
|
||||
model() {
|
||||
|
|
|
@ -6,9 +6,11 @@ export default Route.extend(UnloadModel, {
|
|||
version: service(),
|
||||
|
||||
beforeModel() {
|
||||
return this.get('version').fetchFeatures().then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
return this.get('version')
|
||||
.fetchFeatures()
|
||||
.then(() => {
|
||||
return this._super(...arguments);
|
||||
});
|
||||
},
|
||||
|
||||
model() {
|
||||
|
|
|
@ -51,7 +51,9 @@ export default Service.extend({
|
|||
if (this.get('version')) {
|
||||
return;
|
||||
}
|
||||
let response = yield this.get('store').adapterFor('cluster').health();
|
||||
let response = yield this.get('store')
|
||||
.adapterFor('cluster')
|
||||
.health();
|
||||
this.setVersion(response);
|
||||
return;
|
||||
}),
|
||||
|
@ -61,7 +63,9 @@ export default Service.extend({
|
|||
return;
|
||||
}
|
||||
try {
|
||||
let response = yield this.get('store').adapterFor('cluster').features();
|
||||
let response = yield this.get('store')
|
||||
.adapterFor('cluster')
|
||||
.features();
|
||||
this.setFeatures(response);
|
||||
return;
|
||||
} catch (err) {
|
||||
|
|
|
@ -234,7 +234,11 @@ export default Service.extend(DEFAULTS, {
|
|||
}
|
||||
this.saveExtState(STORAGE_KEYS.FEATURE_STATE, this.get('featureState'));
|
||||
let nextFeature =
|
||||
this.get('featureList').length > 1 ? this.get('featureList').objectAt(1).capitalize() : 'Finish';
|
||||
this.get('featureList').length > 1
|
||||
? this.get('featureList')
|
||||
.objectAt(1)
|
||||
.capitalize()
|
||||
: 'Finish';
|
||||
this.set('nextFeature', nextFeature);
|
||||
let next;
|
||||
if (this.get('currentMachine') === 'secrets' && this.get('featureState') === 'display') {
|
||||
|
|
|
@ -51,6 +51,13 @@
|
|||
Restart guide
|
||||
</button>
|
||||
</li>
|
||||
{{#unless isOSS}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.license" activeClusterName id="license"}}
|
||||
License
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/unless}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.logout" activeClusterName id="logout"}}
|
||||
Sign out
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
<PageHeader as |p|>
|
||||
<p.levelLeft>
|
||||
<h1 class="title is-3">License</h1>
|
||||
</p.levelLeft>
|
||||
</PageHeader>
|
||||
<MessageError @model={{model}} />
|
||||
{{#if isTemporary}}
|
||||
<section class="box is-sideless">
|
||||
<MessageInPage data-test-cluster-status @type="warning" @class="license-warning" data-test-warning-text>
|
||||
Your temporary license expires {{moment-from-now expirationTime}} and your vault will seal. Please enter a valid license below.
|
||||
</MessageInPage>
|
||||
<span class="title is-5" data-test-temp-license>Temporary License</span>
|
||||
<form {{action "saveModel" text on="submit"}}>
|
||||
<div class="box is-shadowless is-fullwidth is-marginless">
|
||||
<div class="field">
|
||||
<label for="license-id" class="is-label">License</label>
|
||||
<div class="control">
|
||||
{{input id="license-id" value=text autocomplete="off" class="input" data-test-text-input="data-test-text-input"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<button type="submit" class="button is-primary" data-test-save-button>Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
{{else}}
|
||||
<section class="box is-sideless">
|
||||
<span class="title is-5">Details</span>
|
||||
{{#if showForm}}
|
||||
<form {{action "saveModel" text on="submit"}}>
|
||||
<div class="field">
|
||||
<label for="license-id" class="is-label">License</label>
|
||||
<div class="control">
|
||||
{{input id="license-id" value=text autocomplete="off" class="input" data-test-text-input="data-test-text-input"}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<button type="submit" class="button is-primary" data-test-save-button>Save</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button type="button" {{action "toggleForm"}} class="button" data-test-cancel-button>Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{{else}}
|
||||
<div class="field box is-fullwidth is-shadowless is-paddingless is-marginless">
|
||||
{{info-table-row label="License ID" value=licenseId}}
|
||||
{{#info-table-row label="Valid from" value=startTime}}
|
||||
{{moment-format model.startTime 'MMM DD, YYYY hh:mm:ss A'}} to {{moment-format expirationTime 'MMM DD, YYYY hh:mm:ss A'}}
|
||||
{{/info-table-row}}
|
||||
</div>
|
||||
<div class="field box is-fullwidth is-shadowless is-paddingless is-marginless">
|
||||
<div class="control">
|
||||
<button type="button" {{action "toggleForm"}} class="button" data-test-enter-button>Enter new license</button>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</section>
|
||||
{{/if}}
|
||||
<section class="box is-sideless is-marginless is-shadowless">
|
||||
<span class="title is-5">Features</span>
|
||||
<div class="field box is-fullwidth is-shadowless is-paddingless is-marginless">
|
||||
{{#each featuresInfo as |info|}}
|
||||
{{#info-table-row label=info.name value=(if info.active "Active" "Not Active") data-test-feature-row="data-test-feature-row"}}
|
||||
{{#if info.active}}
|
||||
<ICon @size=28 @glyph="true" /> <span data-test-feature-status>Active</span>
|
||||
{{else}}
|
||||
<ICon @size=28 @glyph="false" /> <span data-test-feature-status>Not Active</span>
|
||||
{{/if}}
|
||||
{{/info-table-row}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</section>
|
|
@ -0,0 +1,9 @@
|
|||
<LicenseInfo
|
||||
@startTime={{model.startTime}}
|
||||
@expirationTime={{model.expirationTime}}
|
||||
@licenseId={{model.licenseId}}
|
||||
@features={{model.features}}
|
||||
@text={{model.text}}
|
||||
@saveModel={{action "saveModel"}}
|
||||
@model={{model}}
|
||||
/>
|
|
@ -0,0 +1,109 @@
|
|||
import moment from 'moment';
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import sinon from 'sinon';
|
||||
import { create } from 'ember-cli-page-object';
|
||||
import license from '../../pages/components/license-info';
|
||||
|
||||
const component = create(license);
|
||||
|
||||
module('Integration | Component | license info', function(hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
hooks.beforeEach(function() {
|
||||
component.setContext(this);
|
||||
});
|
||||
|
||||
hooks.afterEach(function() {
|
||||
component.removeContext();
|
||||
});
|
||||
|
||||
const LICENSE_WARNING_TEXT = `Warning Your temporary license expires in 30 minutes and your vault will seal. Please enter a valid license below.`;
|
||||
|
||||
test('it renders properly for temporary license', async function(assert) {
|
||||
this.set('licenseId', 'temporary');
|
||||
this.set('expirationTime', moment(moment.now()).add(30, 'minutes'));
|
||||
this.set('startTime', moment.now());
|
||||
this.set('features', ['HSM', 'Namespaces']);
|
||||
await render(
|
||||
hbs`<LicenseInfo @licenseId={{this.licenseId}} @expirationTime={{this.expirationTime}} @startTime={{this.startTime}} @features={{this.features}}/>`
|
||||
);
|
||||
assert.equal(component.warning, LICENSE_WARNING_TEXT, 'it renders warning text including time left');
|
||||
assert.equal(component.hasSaveButton, true, 'it renders the save button');
|
||||
assert.equal(component.hasTextInput, true, 'it renders text input for new license');
|
||||
assert.equal(component.featureRows.length, 12, 'it renders 12 features');
|
||||
assert.equal(component.featureRows[0].featureName, 'HSM', 'it renders HSM feature');
|
||||
assert.equal(component.featureRows[0].featureStatus, 'Active', 'it renders Active for HSM feature');
|
||||
assert.equal(
|
||||
component.featureRows[1].featureName,
|
||||
'Performance Replication',
|
||||
'it renders Performance Replication feature name'
|
||||
);
|
||||
assert.equal(
|
||||
component.featureRows[1].featureStatus,
|
||||
'Not Active',
|
||||
'it renders Not Active for Performance Replication'
|
||||
);
|
||||
});
|
||||
|
||||
test('it renders feature status properly for features associated with license', async function(assert) {
|
||||
this.set('licenseId', 'temporary');
|
||||
this.set('expirationTime', moment(moment.now()).add(30, 'minutes'));
|
||||
this.set('startTime', moment.now());
|
||||
this.set('features', ['HSM', 'Namespaces']);
|
||||
await render(
|
||||
hbs`<LicenseInfo @licenseId={{this.licenseId}} @expirationTime={{this.expirationTime}} @startTime={{this.startTime}} @features={{this.features}}/>`
|
||||
);
|
||||
assert.equal(component.featureRows.length, 12, 'it renders 12 features');
|
||||
let activeFeatures = component.featureRows.filter(f => f.featureStatus === 'Active');
|
||||
assert.equal(activeFeatures.length, 2);
|
||||
});
|
||||
|
||||
test('it renders properly for non-temporary license', async function(assert) {
|
||||
this.set('licenseId', 'test');
|
||||
this.set('expirationTime', moment(moment.now()).add(30, 'minutes'));
|
||||
this.set('startTime', moment.now());
|
||||
this.set('features', ['HSM', 'Namespaces']);
|
||||
await render(
|
||||
hbs`<LicenseInfo @licenseId={{this.licenseId}} @expirationTime={{this.expirationTime}} @startTime={{this.startTime}} @features={{this.features}}/>`
|
||||
);
|
||||
assert.equal(component.hasWarning, false, 'it does not have a warning');
|
||||
assert.equal(component.hasSaveButton, false, 'it does not render the save button');
|
||||
assert.equal(component.hasTextInput, false, 'it does not render the text input for new license');
|
||||
assert.equal(component.hasEnterButton, true, 'it renders the button to toggle license form');
|
||||
});
|
||||
|
||||
test('it shows and hides license form when enter and cancel buttons are clicked', async function(assert) {
|
||||
this.set('licenseId', 'test');
|
||||
this.set('expirationTime', moment(moment.now()).add(30, 'minutes'));
|
||||
this.set('startTime', moment.now());
|
||||
this.set('features', ['HSM', 'Namespaces']);
|
||||
await render(
|
||||
hbs`<LicenseInfo @licenseId={{this.licenseId}} @expirationTime={{this.expirationTime}} @startTime={{this.startTime}} @features={{this.features}}/>`
|
||||
);
|
||||
await component.enterButton();
|
||||
assert.equal(component.hasSaveButton, true, 'it does not render the save button');
|
||||
assert.equal(component.hasTextInput, true, 'it does not render the text input for new license');
|
||||
assert.equal(component.hasEnterButton, false, 'it renders the button to toggle license form');
|
||||
await component.cancelButton();
|
||||
assert.equal(component.hasSaveButton, false, 'it does not render the save button');
|
||||
assert.equal(component.hasTextInput, false, 'it does not render the text input for new license');
|
||||
assert.equal(component.hasEnterButton, true, 'it renders the button to toggle license form');
|
||||
});
|
||||
|
||||
test('it calls saveModel when save button is clicked', async function(assert) {
|
||||
this.set('licenseId', 'temporary');
|
||||
this.set('expirationTime', moment(moment.now()).add(30, 'minutes'));
|
||||
this.set('startTime', moment.now());
|
||||
this.set('features', ['HSM', 'Namespaces']);
|
||||
this.set('saveModel', sinon.spy());
|
||||
await render(
|
||||
hbs`<LicenseInfo @licenseId={{this.licenseId}} @expirationTime={{this.expirationTime}} @startTime={{this.startTime}} @features={{this.features}} @saveModel={{this.saveModel}}/>`
|
||||
);
|
||||
await component.text('ABCDE12345');
|
||||
await component.saveButton();
|
||||
assert.ok(this.get('saveModel').calledOnce);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
import { clickable, fillable, text, isPresent, collection } from 'ember-cli-page-object';
|
||||
|
||||
export default {
|
||||
text: fillable('[data-test-text-input]'),
|
||||
isTemp: isPresent('[data-test-temp-license]'),
|
||||
hasTextInput: isPresent('[data-test-text-input]'),
|
||||
saveButton: clickable('[data-test-save-button]'),
|
||||
hasSaveButton: isPresent('[data-test-save-button]'),
|
||||
enterButton: clickable('[data-test-enter-button]'),
|
||||
hasEnterButton: isPresent('[data-test-enter-button]'),
|
||||
cancelButton: clickable('[data-test-cancel-button]'),
|
||||
hasWarning: isPresent('[data-test-warning-text]'),
|
||||
warning: text('[data-test-warning-text]'),
|
||||
featureRows: collection('[data-test-feature-row]', {
|
||||
featureName: text('[data-test-row-label]'),
|
||||
featureStatus: text('[data-test-feature-status]'),
|
||||
}),
|
||||
};
|
Loading…
Reference in New Issue