Skip to content

Commit

Permalink
fix(core): fix assigning collection items with `updateNestedEntities:…
Browse files Browse the repository at this point in the history
… false`
  • Loading branch information
B4nan committed Sep 8, 2023
1 parent 755ef67 commit e1bfd20
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 1 deletion.
2 changes: 1 addition & 1 deletion packages/core/src/entity/EntityAssigner.ts
Expand Up @@ -185,7 +185,7 @@ export class EntityAssigner {
}

/* istanbul ignore next */
if (options.updateNestedEntities && !options.updateByPrimaryKey && helper(collection[idx])?.isInitialized()) {
if (options.updateNestedEntities && !options.updateByPrimaryKey && collection[idx] && helper(collection[idx])?.isInitialized()) {
return EntityAssigner.assign(collection[idx], item, options);
}

Expand Down
111 changes: 111 additions & 0 deletions tests/features/entity-assigner/assign-collection-items.test.ts
@@ -0,0 +1,111 @@
import { Collection, Entity, ManyToOne, OneToMany, PrimaryKey, Property, Ref, SimpleLogger } from '@mikro-orm/core';
import { MikroORM } from '@mikro-orm/sqlite';
import { v4 } from 'uuid';
import { mockLogger } from '../../helpers';

function generateProducts(amountOfProducts: number, amountOfVariants: number) {
const products = [];
const variants = [];

for (let j = 0; j < amountOfVariants; j++) {
variants.push({
name: `variant-${j}-${Math.random()}`,
});
}

for (let j = 0; j < amountOfProducts; j++) {
products.push({
name: `product-${j}-${Math.random()}`,
variants,
});
}

return products;
}

@Entity()
class Store {

@PrimaryKey({ type: 'uuid' })
id: string = v4();

@Property({ type: 'text' })
name!: string;

@OneToMany(() => Product, product => product.store, { orphanRemoval: true })
products = new Collection<Product>(this);

}

@Entity()
class Product {

@PrimaryKey({ type: 'uuid' })
id: string = v4();

@Property({ type: 'text' })
name!: string;

@ManyToOne(() => Store, { ref: true, onDelete: 'cascade' })
store!: Ref<Store>;

}

let orm: MikroORM;

beforeAll(async () => {
orm = await MikroORM.init({
entities: [Store, Product],
dbName: ':memory:',
loggerFactory: options => new SimpleLogger(options),
});
await orm.schema.createSchema();
});

afterAll(async () => {
await orm.close(true);
});

test('assigning collection items with updateByPrimaryKey: false', async () => {
const data = {
name: 'store',
products: generateProducts(1, 1),
};

const store = orm.em.create(Store, data);
await orm.em.flush();

data.products = generateProducts(2, 1);
orm.em.assign(store, data, { updateByPrimaryKey: false });

const mock = mockLogger(orm, ['query']);
await orm.em.flush();
expect(mock.mock.calls).toEqual([
['[query] begin'],
['[query] insert into `product` (`id`, `name`, `store_id`) values (?, ?, ?) returning `id`'],
['[query] update `product` set `name` = ? where `id` = ?'],
['[query] commit'],
]);
});

test('assigning collection items with updateNestedEntities: false', async () => {
const data = {
name: 'store',
products: generateProducts(1, 1),
};

const store = orm.em.create(Store, data);
await orm.em.flush();

data.products = generateProducts(2, 1);
orm.em.assign(store, data, { updateNestedEntities: false });

const mock = mockLogger(orm, ['query']);
await orm.em.flush();
expect(mock.mock.calls).toEqual([
['[query] begin'],
['[query] insert into `product` (`id`, `name`, `store_id`) values (?, ?, ?), (?, ?, ?) returning `id`'],
['[query] delete from `product` where `id` in (?)'],
['[query] commit'],
]);
});

0 comments on commit e1bfd20

Please sign in to comment.