Skip to content

Commit

Permalink
[Bug]: errors remove to accurately update in template
Browse files Browse the repository at this point in the history
  • Loading branch information
andreyfel authored and igorT committed Sep 23, 2020
1 parent 65ddc5c commit 4c8bb7b
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
70 changes: 70 additions & 0 deletions packages/-ember-data/tests/integration/model-errors-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import 'qunit-dom'; // tell TS consider *.dom extension for assert

// @ts-ignore
import { setComponentTemplate } from '@ember/component';
import { get } from '@ember/object';
import { render, settled } from '@ember/test-helpers';
import Component from '@glimmer/component';

import { module, test } from 'qunit';

import { hbs } from 'ember-cli-htmlbars';
import { setupRenderingTest } from 'ember-qunit';
import { TestContext } from 'ember-test-helpers';

import Model, { attr } from '@ember-data/model';

class Tag extends Model {
@attr('string', {})
name;
}

class ErrorList extends Component<{ model: Model; field: string }> {
get errors() {
const { model, field } = this.args;
return model.errors.errorsFor(field).map(error => error.message);
}
}

const template = hbs`
<ul class="error-list">
{{#each this.errors as |error|}}
<li class="error-list__error">{{error}}</li>
{{/each}}
</ul>
`;

interface CurrentTestContext extends TestContext {
tag: Tag;
}

module('integration/model.errors', function(hooks) {
setupRenderingTest(hooks);

hooks.beforeEach(function() {
let { owner } = this;

owner.register('model:tag', Tag);
owner.register('component:error-list', setComponentTemplate(template, ErrorList));
});

test('Model errors are autotracked', async function(this: CurrentTestContext, assert) {
this.tag = this.owner.lookup('service:store').createRecord('tag');
// @ts-ignore
const errors = get(this.tag, 'errors');

await render(hbs`<ErrorList @model={{this.tag}} @field="name"/>`);

assert.dom('.error-list__error').doesNotExist();

errors.add('name', 'the-error');
await settled();

assert.dom('.error-list__error').hasText('the-error');

errors.remove('name');
await settled();

assert.dom('.error-list__error').doesNotExist();
});
});
10 changes: 10 additions & 0 deletions packages/model/addon/-private/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,16 @@ export default ArrayProxy.extend(DeprecatedEvented, {

let content = this.rejectBy('attribute', attribute);
get(this, 'content').setObjects(content);

// Although errorsByAttributeName.delete is technically enough to sync errors state, we also
// must mutate the array as well for autotracking
let errors = this.errorsFor(attribute);
for (let i = 0; i < errors.length; i++) {
if (errors[i].attribute === attribute) {
// .replace from Ember.NativeArray is necessary. JS splice will not work.
errors.replace(i, 1);
}
}
get(this, 'errorsByAttributeName').delete(attribute);

this.notifyPropertyChange(attribute);
Expand Down

0 comments on commit 4c8bb7b

Please sign in to comment.