add: test (#224)
* add: test * feat: updateAssociation Skip reverseAssociationPair * feat: reverseAssociationPair with HasMany && HasOne
This commit is contained in:
parent
4ce41cf7b2
commit
e76eb1edac
163
packages/database/src/__tests__/repository/create.test.ts
Normal file
163
packages/database/src/__tests__/repository/create.test.ts
Normal file
@ -0,0 +1,163 @@
|
||||
import { mockDatabase } from '../index';
|
||||
import Database from '../../database';
|
||||
|
||||
describe('create with hasMany', () => {
|
||||
let db: Database;
|
||||
let Post;
|
||||
let User;
|
||||
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
db = mockDatabase();
|
||||
|
||||
await db.clean({ drop: true });
|
||||
User = db.collection({
|
||||
name: 'users',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'posts',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Post = db.collection({
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'title',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'user',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
});
|
||||
|
||||
it('should save associations with reverseField value', async () => {
|
||||
const u1 = await db.getRepository('users').create({
|
||||
values: {
|
||||
name: 'u1',
|
||||
posts: [{ title: 't1', user: null }],
|
||||
},
|
||||
});
|
||||
|
||||
const p1 = await db.getRepository('posts').findOne();
|
||||
// @ts-ignore
|
||||
expect(await p1.getUser()).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('create with belongsToMany', () => {
|
||||
let db: Database;
|
||||
let Post;
|
||||
let Tag;
|
||||
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
db = mockDatabase();
|
||||
Post = db.collection({
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'title',
|
||||
},
|
||||
{
|
||||
type: 'belongsToMany',
|
||||
name: 'tags',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Tag = db.collection({
|
||||
name: 'tags',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'belongsToMany',
|
||||
name: 'posts',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
});
|
||||
|
||||
it('should save associations with reverseField value', async () => {
|
||||
const t1 = await db.getRepository('tags').create({
|
||||
values: {
|
||||
name: 't1',
|
||||
},
|
||||
});
|
||||
|
||||
const p1 = await db.getRepository('posts').create({
|
||||
values: {
|
||||
title: 'p1',
|
||||
tags: [{ id: t1.get('id'), name: 't1', posts: [] }],
|
||||
},
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
expect(await p1.countTags()).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('create', () => {
|
||||
let db: Database;
|
||||
let User;
|
||||
let Post;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = mockDatabase();
|
||||
User = db.collection({
|
||||
name: 'users',
|
||||
fields: [
|
||||
{ type: 'string', name: 'name' },
|
||||
{ type: 'hasMany', name: 'posts' },
|
||||
],
|
||||
});
|
||||
|
||||
Post = db.collection({
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{ type: 'string', name: 'title' },
|
||||
{ type: 'belongsTo', name: 'user' },
|
||||
],
|
||||
});
|
||||
await db.sync();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
test('create with association', async () => {
|
||||
const u1 = await User.repository.create({
|
||||
values: {
|
||||
name: 'u1',
|
||||
posts: [{ title: 'u1p1' }],
|
||||
},
|
||||
});
|
||||
|
||||
expect(u1.name).toEqual('u1');
|
||||
expect(await u1.countPosts()).toEqual(1);
|
||||
});
|
||||
});
|
@ -1,43 +0,0 @@
|
||||
import { mockDatabase } from '../index';
|
||||
import Database from '../../database';
|
||||
|
||||
describe('create', () => {
|
||||
let db: Database;
|
||||
let User;
|
||||
let Post;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = mockDatabase();
|
||||
User = db.collection({
|
||||
name: 'users',
|
||||
fields: [
|
||||
{ type: 'string', name: 'name' },
|
||||
{ type: 'hasMany', name: 'posts' },
|
||||
],
|
||||
});
|
||||
|
||||
Post = db.collection({
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{ type: 'string', name: 'title' },
|
||||
{ type: 'belongsTo', name: 'user' },
|
||||
],
|
||||
});
|
||||
await db.sync();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
});
|
||||
test('create with association', async () => {
|
||||
const u1 = await User.repository.create({
|
||||
values: {
|
||||
name: 'u1',
|
||||
posts: [{ title: 'u1p1' }],
|
||||
},
|
||||
});
|
||||
|
||||
expect(u1.name).toEqual('u1');
|
||||
expect(await u1.countPosts()).toEqual(1);
|
||||
});
|
||||
});
|
@ -6,7 +6,7 @@ import {
|
||||
HasOne,
|
||||
Hookable,
|
||||
ModelCtor,
|
||||
Transactionable
|
||||
Transactionable,
|
||||
} from 'sequelize';
|
||||
import { Model } from './model';
|
||||
import { TransactionAble } from './repository';
|
||||
@ -64,6 +64,7 @@ interface UpdateAssociationOptions extends Transactionable, Hookable {
|
||||
updateAssociationValues?: string[];
|
||||
sourceModel?: Model;
|
||||
context?: any;
|
||||
associationContext?: any;
|
||||
}
|
||||
|
||||
export async function updateModelByValues(instance: Model, values: UpdateValue, options?: UpdateOptions) {
|
||||
@ -164,6 +165,37 @@ export async function updateAssociations(instance: Model, values: any, options:
|
||||
}
|
||||
}
|
||||
|
||||
function isReverseAssociationPair(a: any, b: any) {
|
||||
const typeSet = new Set();
|
||||
typeSet.add(a.associationType);
|
||||
typeSet.add(b.associationType);
|
||||
|
||||
if (typeSet.size == 1 && typeSet.has('BelongsToMany')) {
|
||||
return (
|
||||
a.through.tableName === b.through.tableName &&
|
||||
a.target.name === b.source.name &&
|
||||
b.target.name === a.source.name &&
|
||||
a.foreignKey === b.otherKey &&
|
||||
a.sourceKey === b.targetKey &&
|
||||
a.otherKey === b.foreignKey &&
|
||||
a.targetKey === b.sourceKey
|
||||
);
|
||||
}
|
||||
|
||||
if ((typeSet.has('HasOne') && typeSet.has('BelongsTo')) || (typeSet.has('HasMany') && typeSet.has('BelongsTo'))) {
|
||||
const sourceAssoc = a.associationType == 'BelongsTo' ? b : a;
|
||||
const targetAssoc = sourceAssoc == a ? b : a;
|
||||
|
||||
return (
|
||||
sourceAssoc.source.name === targetAssoc.target.name &&
|
||||
sourceAssoc.foreignKey === targetAssoc.foreignKey &&
|
||||
sourceAssoc.sourceKey === targetAssoc.targetKey
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* update model association by key
|
||||
* @param instance
|
||||
@ -183,6 +215,10 @@ export async function updateAssociation(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (options.associationContext && isReverseAssociationPair(association, options.associationContext)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (association.associationType) {
|
||||
case 'HasOne':
|
||||
case 'BelongsTo':
|
||||
@ -280,7 +316,12 @@ export async function updateSingleAssociation(
|
||||
await instance.update(value, { ...options, transaction });
|
||||
}
|
||||
|
||||
await updateAssociations(instance, value, { ...options, transaction, updateAssociationValues: keys });
|
||||
await updateAssociations(instance, value, {
|
||||
...options,
|
||||
transaction,
|
||||
associationContext: association,
|
||||
updateAssociationValues: keys,
|
||||
});
|
||||
model.setDataValue(key, instance);
|
||||
if (!options.transaction) {
|
||||
await transaction.commit();
|
||||
@ -290,7 +331,12 @@ export async function updateSingleAssociation(
|
||||
}
|
||||
|
||||
const instance = await model[createAccessor](value, { context, transaction });
|
||||
await updateAssociations(instance, value, { ...options, transaction, updateAssociationValues: keys });
|
||||
await updateAssociations(instance, value, {
|
||||
...options,
|
||||
transaction,
|
||||
associationContext: association,
|
||||
updateAssociationValues: keys,
|
||||
});
|
||||
model.setDataValue(key, instance);
|
||||
// @ts-ignore
|
||||
if (association.targetKey) {
|
||||
@ -392,7 +438,12 @@ export async function updateMultipleAssociation(
|
||||
if (isUndefinedOrNull(item[pk])) {
|
||||
// create new record
|
||||
const instance = await model[createAccessor](item, accessorOptions);
|
||||
await updateAssociations(instance, item, { ...options, transaction, updateAssociationValues: keys });
|
||||
await updateAssociations(instance, item, {
|
||||
...options,
|
||||
transaction,
|
||||
associationContext: association,
|
||||
updateAssociationValues: keys,
|
||||
});
|
||||
list3.push(instance);
|
||||
} else {
|
||||
// set & update record
|
||||
@ -405,7 +456,12 @@ export async function updateMultipleAssociation(
|
||||
if (updateAssociationValues.includes(key)) {
|
||||
await instance.update(item, { ...options, transaction });
|
||||
}
|
||||
await updateAssociations(instance, item, { ...options, transaction, updateAssociationValues: keys });
|
||||
await updateAssociations(instance, item, {
|
||||
...options,
|
||||
transaction,
|
||||
associationContext: association,
|
||||
updateAssociationValues: keys,
|
||||
});
|
||||
list3.push(instance);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user