Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests to demonstrate async-to-async unloadAll(<type>) issue (#9151) #9185

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 163 additions & 1 deletion tests/main/tests/integration/records/unload-all-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { module, test } from 'qunit';

import { setupTest } from 'ember-qunit';

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

module('Integration | Records | unloadAll', function (hooks) {
setupTest(hooks);
Expand Down Expand Up @@ -392,4 +392,166 @@ module('Integration | Records | unloadAll', function (hooks) {
await settled();
assert.strictEqual(store.peekAll('post').length, 0, '0 posts in the store at the end');
});

const TYPES = ['post', 'category', 'author'];
TYPES.forEach((type) => {
const RemainingTypes = TYPES.filter((t) => t !== type);
RemainingTypes.forEach((remainingType) => {
const finalType = RemainingTypes.find((t) => t !== remainingType);
const UnloadOrder = [type, remainingType, finalType];

test(`unloadAll(<type>) works when some of the related records of another type are also unloaded (${UnloadOrder.join(
' => '
)})`, function (assert) {
const { owner } = this;

// since async relationships are retainers, we make all
// sides here async to dial up the potential cycle
// we also do a three-way cycle to add extra complexity
class Post extends Model {
@attr title;
@hasMany('author', { async: true, inverse: 'posts' }) authors;
}
class Category extends Model {
@attr name;
@hasMany('author', { async: true, inverse: 'categories' }) authors;
}
class Author extends Model {
@attr name;
@hasMany('category', { async: true, inverse: 'authors' }) categories;
@hasMany('post', { async: true, inverse: 'authors' }) posts;
}

owner.register('model:post', Post);
owner.register('model:category', Category);
owner.register('model:author', Author);
const store = owner.lookup('service:store');

// push some data into the store
store.push({
data: [
{
type: 'post',
id: '1',
attributes: {
title: 'Lorem ipsum',
},
relationships: {
authors: {
data: [{ type: 'author', id: '1' }],
},
},
},
{
type: 'category',
id: '1',
attributes: {
name: 'Lorem ipsum',
},
relationships: {
authors: {
data: [{ type: 'author', id: '1' }],
},
},
},
{
type: 'author',
id: '1',
attributes: {
name: 'Lorem ipsum',
},
relationships: {
posts: {
data: [{ type: 'post', id: '1' }],
},
categories: {
data: [{ type: 'category', id: '1' }],
},
},
},
],
});

// unload all the records of each type by type
UnloadOrder.forEach((type) => {
store.unloadAll(type);
});

// assert that all the records are unloaded
assert.strictEqual(store.peekAll('post').length, 0, '0 posts in the store');
assert.strictEqual(store.peekAll('category').length, 0, '0 categories in the store');
assert.strictEqual(store.peekAll('author').length, 0, '0 authors in the store');
});

test(`unloadAll(<type>) works when some of the related records of another type were never loaded (${UnloadOrder.join(
' => '
)})`, function (assert) {
const { owner } = this;

// since async relationships are retainers, we make all
// sides here async to dial up the potential cycle
// we also do a three-way cycle to add extra complexity
class Post extends Model {
@attr title;
@hasMany('author', { async: true, inverse: 'posts' }) authors;
}
class Category extends Model {
@attr name;
@hasMany('author', { async: true, inverse: 'categories' }) authors;
}
class Author extends Model {
@attr name;
@hasMany('category', { async: true, inverse: 'authors' }) categories;
@hasMany('post', { async: true, inverse: 'authors' }) posts;
}

owner.register('model:post', Post);
owner.register('model:category', Category);
owner.register('model:author', Author);
const store = owner.lookup('service:store');

// push some data into the store
// and make sure all relationships are materialized
// note: we intentionally do not load author
store.push({
data: [
{
type: 'post',
id: '1',
attributes: {
title: 'Lorem ipsum',
},
relationships: {
authors: {
data: [{ type: 'author', id: '1' }],
},
},
},
{
type: 'category',
id: '1',
attributes: {
text: 'Lorem ipsum',
},
relationships: {
authors: {
data: [{ type: 'author', id: '1' }],
},
},
},
],
});

// unload all the records of each type by type
UnloadOrder.forEach((type) => {
store.unloadAll(type);
});

// assert that all the records are unloaded
assert.strictEqual(store.peekAll('post').length, 0, '0 posts in the store');
assert.strictEqual(store.peekAll('category').length, 0, '0 categories in the store');
assert.strictEqual(store.peekAll('author').length, 0, '0 authors in the store');
});
});
});
});
Loading