undeexcepturi
Version:
TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.
159 lines (126 loc) • 4.45 kB
text/typescript
import { Entity, OneToOne, PrimaryKey, Property, RequiredEntityData } from '@mikro-orm/core';
import { MikroORM } from '@mikro-orm/sqlite';
()
class User {
()
id!: number;
({ nullable: true })
name!: string;
(() => Project, project => project.owner, {
owner: true,
nullable: false,
})
project!: Project | null;
}
()
class Project {
()
id!: number;
({ nullable: true })
name!: string;
(() => User, user => user.project, { nullable: false })
owner?: User;
}
let orm: MikroORM;
beforeAll(async () => {
orm = await MikroORM.init({
entities: [Project, User],
dbName: ':memory:',
});
});
beforeEach(async () => {
await orm.schema.refreshDatabase();
});
afterAll(() => orm.close(true));
async function createUser(props: RequiredEntityData<User>) {
const u = orm.em.create(User, {
...props,
});
await orm.em.flush();
orm.em.clear();
return orm.em.findOneOrFail(User, u.id, { populate: ['project'] });
}
async function createProject(props: RequiredEntityData<Project>) {
const project = orm.em.create(Project, {
...props,
});
await orm.em.flush();
orm.em.clear();
return orm.em.findOneOrFail(Project, project.id, { populate: ['owner'] });
}
describe('Required 1-to-1 relation propagation', () => {
test('Can create a required 1-to-1 relationship', async () => {
let project = orm.em.create(Project, {
name: 'Project 1',
});
let owner = await createUser({ name: 'User 1', project });
// Refetch and check relation (owner)
owner = await orm.em.findOneOrFail(User, owner.id, { populate: ['project'] });
expect(owner.project?.name).toBe('Project 1');
// Refetch and check un-linked entity (inverse side)
project = await orm.em.findOneOrFail(Project, project.id, { populate: ['owner'] });
expect(project.owner?.name).toBe('User 1');
});
// Swapping related entities (replacing one relation with a new entity)
test('can swap existing inverse entity on owner side', async () => {
let project1 = orm.em.create(Project, {
name: 'Project 1',
});
let owner = await createUser({ name: 'User 1', project: project1 });
project1 = owner.project as Project;
// Create new project and assign to user
let project2 = orm.em.create(Project, {
name: 'Project 2',
});
owner.project = project2;
orm.em.persist(project2);
// Remove previous
orm.em.remove(project1);
// Check value before flush
expect(owner.project.name).toBe('Project 2');
expect(project2.owner).toBeTruthy();
// Flush changes
await orm.em.flush();
orm.em.clear();
// Refetch and check relation (owner)
owner = await orm.em.findOneOrFail(User, owner.id, { populate: ['project'] });
expect(owner.project?.name).toBe('Project 2');
// Refetch and check new entity (inverse side)
project2 = await orm.em.findOneOrFail(Project, project2.id, { populate: ['owner'] });
expect(project2.owner).toBeTruthy();
// Refetch and check removed entity (inverse side)
const oldProject = await orm.em.findOne(Project, project1.id);
expect(oldProject).toBeFalsy();
});
test('can swap existing owner entity on inverse side', async () => {
let owner1 = orm.em.create(User, {
name: 'User 1',
});
let project = await createProject({ name: 'Project 1', owner: owner1 });
owner1 = project.owner as User;
// Create new owner and assign to project
let owner2 = orm.em.create(User, {
name: 'User 2',
});
project.owner = owner2;
orm.em.persist(owner2);
// Check value before flush
// Remove previous
orm.em.remove(owner1);
expect(project.owner.name).toBe('User 2');
expect(owner2.project).toBeTruthy();
expect(owner1.project).toBeFalsy();
// Flush changes
await orm.em.flush();
orm.em.clear();
// Refetch and check relation (inverse side)
project = await orm.em.findOneOrFail(Project, project.id, { populate: ['owner'] });
expect(project.owner?.name).toBe('User 2');
// Refetch and check new entity (owner side)
owner2 = await orm.em.findOneOrFail(User, owner2.id, { populate: ['project'] });
expect(owner2.project).toBeTruthy();
// Refetch and check removed entity (inverse side)
const oldOwner = await orm.em.findOne(User, owner1.id);
expect(oldOwner).toBeFalsy();
});
});