diff --git a/packages/store/addon/-private/store-service.ts b/packages/store/addon/-private/store-service.ts index 9e6af5b7cca..bdd68fe05b5 100644 --- a/packages/store/addon/-private/store-service.ts +++ b/packages/store/addon/-private/store-service.ts @@ -3,7 +3,7 @@ */ import { getOwner, setOwner } from '@ember/application'; import { assert, deprecate } from '@ember/debug'; -import { _backburner as emberBackburner, run } from '@ember/runloop'; +import { _backburner as emberBackburner } from '@ember/runloop'; import Service from '@ember/service'; import { registerWaiter, unregisterWaiter } from '@ember/test'; import { DEBUG } from '@glimmer/env'; @@ -642,7 +642,7 @@ class Store extends Service { recordData.setIsDeleted(identifier, true); if (recordData.isNew(identifier)) { - run(() => { + emberBackburner.join(() => { this._instanceCache.unloadRecord(identifier); }); } diff --git a/tests/main/tests/acceptance/relationships/has-many-test.js b/tests/main/tests/acceptance/relationships/has-many-test.js index 2d0119508b4..33dae04cf28 100644 --- a/tests/main/tests/acceptance/relationships/has-many-test.js +++ b/tests/main/tests/acceptance/relationships/has-many-test.js @@ -2,7 +2,7 @@ import ArrayProxy from '@ember/array/proxy'; import { action } from '@ember/object'; import { sort } from '@ember/object/computed'; import { inject as service } from '@ember/service'; -import { click, find, findAll, render } from '@ember/test-helpers'; +import { click, find, findAll, render, rerender } from '@ember/test-helpers'; import Component from '@glimmer/component'; import Ember from 'ember'; @@ -1211,6 +1211,101 @@ module('autotracking has-many', function (hooks) { assert.deepEqual(names, ['RGB', 'RGB'], 'rendered 2 children'); }); + test('We can re-render hasMany with filter after deleting a record', async function (assert) { + this.owner.register( + 'model:person', + class extends Model { + @attr name; + @hasMany('person', { async: false, inverse: 'parent' }) + children; + @belongsTo('person', { async: false, inverse: 'children' }) + parent; + } + ); + class ChildrenList extends Component { + @service store; + + get children() { + return this.args.children.filter((x) => !x.isDeleted); + } + + @action + createChild() { + const parent = this.args.person; + const name = 'RGB'; + this.store.createRecord('person', { name, parent }); + } + + @action + deleteChild(child) { + child.deleteRecord(); + } + } + + let layout = hbs` + + +

{{this.children.length}}

+ + `; + this.owner.register('component:children-list', ChildrenList); + this.owner.register('template:components/children-list', layout); + + this.person = store.push({ + data: { + type: 'person', + id: '1', + attributes: { name: 'Doodad' }, + }, + }); + this.children = await this.person.children; + + await render(hbs``); + + let names = findAll('li > span').map((e) => e.textContent); + + assert.deepEqual(names, [], 'rendered no children'); + + store.push({ + data: { + type: 'person', + id: '2', + attributes: { name: 'Rey' }, + relationships: { + parent: { data: { id: '1', type: 'person' } }, + }, + }, + }); + await rerender(); + + names = findAll('li > span').map((e) => e.textContent); + assert.deepEqual(names, ['Rey'], 'rendered one child'); + + await click('#createChild'); + + names = findAll('li > span').map((e) => e.textContent); + assert.deepEqual(names, ['Rey', 'RGB'], 'rendered 1 existing and 1 created child'); + + await click('#createChild'); + + names = findAll('li > span').map((e) => e.textContent); + assert.deepEqual(names, ['Rey', 'RGB', 'RGB'], 'rendered 1 existing and 2 created children'); + + await click(find('.delete-child')); + + names = findAll('li > span').map((e) => e.textContent); + assert.deepEqual(names, ['RGB', 'RGB'], 'rendered 2 created children after deleting existing'); + + await click(find('.delete-child')); + + names = findAll('li > span').map((e) => e.textContent); + assert.deepEqual(names, ['RGB'], 'rendered 1 created children after deleting existing'); + }); + test('We can re-render hasMany with peekAll', async function (assert) { class PeopleList extends Component { @service store;