mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-24 23:48:13 -05:00
fix double-render issues with validation-state mixin
This commit is contained in:
parent
719aed29cf
commit
295f2cce96
4 changed files with 68 additions and 38 deletions
|
@ -1,7 +1,8 @@
|
||||||
import Mixin from 'ember-metal/mixin';
|
import Mixin from 'ember-metal/mixin';
|
||||||
import computed from 'ember-computed';
|
|
||||||
import {isEmpty} from 'ember-utils';
|
import {isEmpty} from 'ember-utils';
|
||||||
import {A as emberA} from 'ember-array/utils';
|
import {A as emberA} from 'ember-array/utils';
|
||||||
|
import observer from 'ember-metal/observer';
|
||||||
|
import run from 'ember-runloop';
|
||||||
|
|
||||||
export default Mixin.create({
|
export default Mixin.create({
|
||||||
|
|
||||||
|
@ -9,26 +10,36 @@ export default Mixin.create({
|
||||||
property: '',
|
property: '',
|
||||||
hasValidated: emberA(),
|
hasValidated: emberA(),
|
||||||
|
|
||||||
hasError: computed('errors.[]', 'property', 'hasValidated.[]', function () {
|
hasError: false,
|
||||||
|
|
||||||
|
setHasError() {
|
||||||
let property = this.get('property');
|
let property = this.get('property');
|
||||||
let errors = this.get('errors');
|
let errors = this.get('errors');
|
||||||
let hasValidated = this.get('hasValidated');
|
let hasValidated = this.get('hasValidated');
|
||||||
|
|
||||||
// if we aren't looking at a specific property we always want an error class
|
// if we aren't looking at a specific property we always want an error class
|
||||||
if (!property && !isEmpty(errors)) {
|
if (!property && errors && !errors.get('isEmpty')) {
|
||||||
return true;
|
this.set('hasError', true);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we haven't yet validated this field, there is no validation class needed
|
// If we haven't yet validated this field, there is no validation class needed
|
||||||
if (!hasValidated || !hasValidated.includes(property)) {
|
if (!hasValidated || !hasValidated.includes(property)) {
|
||||||
return false;
|
this.set('hasError', false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors) {
|
if (errors && !isEmpty(errors.errorsFor(property))) {
|
||||||
return errors.get(property);
|
this.set('hasError', true);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
this.set('hasError', false);
|
||||||
})
|
},
|
||||||
|
|
||||||
|
hasErrorObserver: observer('errors.[]', 'property', 'hasValidated.[]', function () {
|
||||||
|
run.once(this, 'setHasError');
|
||||||
|
// this.setHasError();
|
||||||
|
}).on('init')
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {describe, it} from 'mocha';
|
||||||
import {setupComponentTest} from 'ember-mocha';
|
import {setupComponentTest} from 'ember-mocha';
|
||||||
import hbs from 'htmlbars-inline-precompile';
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
import NavItem from 'ghost-admin/models/navigation-item';
|
import NavItem from 'ghost-admin/models/navigation-item';
|
||||||
|
import wait from 'ember-test-helpers/wait';
|
||||||
|
|
||||||
describe('Integration: Component: gh-navitem', function () {
|
describe('Integration: Component: gh-navitem', function () {
|
||||||
setupComponentTest('gh-navitem', {
|
setupComponentTest('gh-navitem', {
|
||||||
|
@ -100,6 +101,7 @@ describe('Integration: Component: gh-navitem', function () {
|
||||||
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl}}`);
|
this.render(hbs`{{gh-navitem navItem=navItem baseUrl=baseUrl}}`);
|
||||||
let $item = this.$('.gh-blognav-item');
|
let $item = this.$('.gh-blognav-item');
|
||||||
|
|
||||||
|
return wait().then(() => {
|
||||||
expect($item.hasClass('gh-blognav-item--error')).to.be.true;
|
expect($item.hasClass('gh-blognav-item--error')).to.be.true;
|
||||||
expect($item.find('.gh-blognav-label').hasClass('error')).to.be.true;
|
expect($item.find('.gh-blognav-label').hasClass('error')).to.be.true;
|
||||||
expect($item.find('.gh-blognav-label .response').text().trim()).to.equal('You must specify a label');
|
expect($item.find('.gh-blognav-label .response').text().trim()).to.equal('You must specify a label');
|
||||||
|
@ -107,3 +109,4 @@ describe('Integration: Component: gh-navitem', function () {
|
||||||
expect($item.find('.gh-blognav-url .response').text().trim()).to.equal('You must specify a URL or relative path');
|
expect($item.find('.gh-blognav-url .response').text().trim()).to.equal('You must specify a URL or relative path');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Service from 'ember-service';
|
||||||
import EmberObject from 'ember-object';
|
import EmberObject from 'ember-object';
|
||||||
import run from 'ember-runloop';
|
import run from 'ember-runloop';
|
||||||
import DS from 'ember-data';
|
import DS from 'ember-data';
|
||||||
|
import wait from 'ember-test-helpers/wait';
|
||||||
|
|
||||||
const {Errors} = DS;
|
const {Errors} = DS;
|
||||||
|
|
||||||
|
@ -195,6 +196,7 @@ describe('Integration: Component: gh-tag-settings-form', function () {
|
||||||
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
|
{{gh-tag-settings-form tag=tag setProperty=(action 'setProperty')}}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
return wait().then(() => {
|
||||||
let nameFormGroup = this.$('input[name="name"]').closest('.form-group');
|
let nameFormGroup = this.$('input[name="name"]').closest('.form-group');
|
||||||
expect(nameFormGroup.hasClass('error'), 'name form group has error state').to.be.true;
|
expect(nameFormGroup.hasClass('error'), 'name form group has error state').to.be.true;
|
||||||
expect(nameFormGroup.find('.response').length, 'name form group has error message').to.equal(1);
|
expect(nameFormGroup.find('.response').length, 'name form group has error message').to.equal(1);
|
||||||
|
@ -214,6 +216,7 @@ describe('Integration: Component: gh-tag-settings-form', function () {
|
||||||
expect(metaDescriptionFormGroup.hasClass('error'), 'metaDescription form group has error state').to.be.true;
|
expect(metaDescriptionFormGroup.hasClass('error'), 'metaDescription form group has error state').to.be.true;
|
||||||
expect(metaDescriptionFormGroup.find('.response').length, 'metaDescription form group has error message').to.equal(1);
|
expect(metaDescriptionFormGroup.find('.response').length, 'metaDescription form group has error message').to.equal(1);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('displays char count for text fields', function () {
|
it('displays char count for text fields', function () {
|
||||||
this.render(hbs`
|
this.render(hbs`
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {setupComponentTest} from 'ember-mocha';
|
||||||
import hbs from 'htmlbars-inline-precompile';
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
import EmberObject from 'ember-object';
|
import EmberObject from 'ember-object';
|
||||||
import DS from 'ember-data';
|
import DS from 'ember-data';
|
||||||
|
import wait from 'ember-test-helpers/wait';
|
||||||
|
|
||||||
const {Errors} = DS;
|
const {Errors} = DS;
|
||||||
|
|
||||||
|
@ -27,10 +28,13 @@ describe('Integration: Component: gh-validation-status-container', function () {
|
||||||
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
|
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
|
||||||
{{/gh-validation-status-container}}
|
{{/gh-validation-status-container}}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
return wait().then(() => {
|
||||||
expect(this.$('.gh-test')).to.have.length(1);
|
expect(this.$('.gh-test')).to.have.length(1);
|
||||||
expect(this.$('.gh-test').hasClass('success')).to.be.false;
|
expect(this.$('.gh-test').hasClass('success')).to.be.false;
|
||||||
expect(this.$('.gh-test').hasClass('error')).to.be.false;
|
expect(this.$('.gh-test').hasClass('error')).to.be.false;
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('has success class when valid', function () {
|
it('has success class when valid', function () {
|
||||||
this.get('testObject.hasValidated').push('name');
|
this.get('testObject.hasValidated').push('name');
|
||||||
|
@ -39,10 +43,13 @@ describe('Integration: Component: gh-validation-status-container', function () {
|
||||||
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
|
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
|
||||||
{{/gh-validation-status-container}}
|
{{/gh-validation-status-container}}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
return wait().then(() => {
|
||||||
expect(this.$('.gh-test')).to.have.length(1);
|
expect(this.$('.gh-test')).to.have.length(1);
|
||||||
expect(this.$('.gh-test').hasClass('success')).to.be.true;
|
expect(this.$('.gh-test').hasClass('success')).to.be.true;
|
||||||
expect(this.$('.gh-test').hasClass('error')).to.be.false;
|
expect(this.$('.gh-test').hasClass('error')).to.be.false;
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('has error class when invalid', function () {
|
it('has error class when invalid', function () {
|
||||||
this.get('testObject.hasValidated').push('name');
|
this.get('testObject.hasValidated').push('name');
|
||||||
|
@ -52,10 +59,13 @@ describe('Integration: Component: gh-validation-status-container', function () {
|
||||||
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
|
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
|
||||||
{{/gh-validation-status-container}}
|
{{/gh-validation-status-container}}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
return wait().then(() => {
|
||||||
expect(this.$('.gh-test')).to.have.length(1);
|
expect(this.$('.gh-test')).to.have.length(1);
|
||||||
expect(this.$('.gh-test').hasClass('success')).to.be.false;
|
expect(this.$('.gh-test').hasClass('success')).to.be.false;
|
||||||
expect(this.$('.gh-test').hasClass('error')).to.be.true;
|
expect(this.$('.gh-test').hasClass('error')).to.be.true;
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('still renders if hasValidated is undefined', function () {
|
it('still renders if hasValidated is undefined', function () {
|
||||||
this.set('testObject.hasValidated', undefined);
|
this.set('testObject.hasValidated', undefined);
|
||||||
|
@ -64,6 +74,9 @@ describe('Integration: Component: gh-validation-status-container', function () {
|
||||||
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
|
{{#gh-validation-status-container class="gh-test" property="name" errors=testObject.errors hasValidated=testObject.hasValidated}}
|
||||||
{{/gh-validation-status-container}}
|
{{/gh-validation-status-container}}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
return wait().then(() => {
|
||||||
expect(this.$('.gh-test')).to.have.length(1);
|
expect(this.$('.gh-test')).to.have.length(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue