quaerateum
Version:
Simple 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 JS.
682 lines (584 loc) • 27.4 kB
text/typescript
import { unlinkSync } from 'fs';
import { Collection, EntityManager, JavaScriptMetadataProvider, MikroORM, Utils } from '../lib';
import { initORMSqlite, wipeDatabaseSqlite } from './bootstrap';
import { SqliteDriver } from '../lib/drivers/SqliteDriver';
import { Logger } from '../lib/utils';
import { EntityMetadata } from '../lib/decorators';
const { Author3 } = require('./entities-js').Author3;
const { Book3 } = require('./entities-js').Book3;
const { BookTag3 } = require('./entities-js').BookTag3;
const { Publisher3 } = require('./entities-js').Publisher3;
const { Test3 } = require('./entities-js').Test3;
/**
* @class EntityManagerSqliteTest
*/
describe('EntityManagerSqlite', () => {
let orm: MikroORM;
beforeAll(async () => orm = await initORMSqlite());
beforeEach(async () => wipeDatabaseSqlite(orm.em));
test('isConnected()', async () => {
expect(await orm.isConnected()).toBe(true);
await orm.close(true);
expect(await orm.isConnected()).toBe(false);
await orm.connect();
expect(await orm.isConnected()).toBe(true);
});
test('onUpdate should be re-hydrated when loading metadata from cache', async () => {
const provider = new JavaScriptMetadataProvider(orm.config);
const cacheAdapter = orm.config.getCacheAdapter();
const cache = cacheAdapter.get('Author3.js');
const meta = {} as EntityMetadata;
provider.loadFromCache(meta, cache);
expect(meta.properties['updatedAt'].onUpdate).toBeDefined();
expect(meta.properties['updatedAt'].onUpdate!()).toBeInstanceOf(Date);
});
test('should return sqlite driver', async () => {
const driver = orm.em.getDriver<SqliteDriver>();
expect(driver instanceof SqliteDriver).toBe(true);
expect(await driver.findOne(Book3.name, { foo: 'bar' })).toBeNull();
expect(await driver.nativeInsert(BookTag3.name, { name: 'tag', books: [1] })).not.toBeNull();
expect(await driver.getConnection().execute('SELECT 1 as count')).toEqual([{ count: 1 }]);
expect(await driver.find(BookTag3.name, { books: [1] })).not.toBeNull();
});
test('driver appends errored query', async () => {
const driver = orm.em.getDriver<SqliteDriver>();
const err1 = `SQLITE_ERROR: no such table: not_existing\n in query: INSERT INTO "not_existing" ("foo") VALUES (?)\n with params: ["bar"]`;
await expect(driver.nativeInsert('not_existing', { foo: 'bar' })).rejects.toThrowError(err1);
const err2 = `SQLITE_ERROR: no such table: not_existing\n in query: DELETE FROM "not_existing"`;
await expect(driver.nativeDelete('not_existing', {})).rejects.toThrowError(err2);
});
test('should convert entity to PK when trying to search by entity', async () => {
const repo = orm.em.getRepository(Author3);
const author = new Author3('name', 'email');
await repo.persist(author);
const a = await repo.findOne(author);
const authors = await repo.find({ id: author });
expect(a).toBe(author);
expect(authors[0]).toBe(author);
});
test('transactions', async () => {
const god1 = new Author3('God1', 'hello@heaven1.god');
await orm.em.beginTransaction();
await orm.em.persist(god1);
await orm.em.rollback();
const res1 = await orm.em.findOne(Author3, { name: 'God1' });
expect(res1).toBeNull();
await orm.em.beginTransaction();
const god2 = new Author3('God2', 'hello@heaven2.god');
await orm.em.persist(god2);
await orm.em.commit();
const res2 = await orm.em.findOne(Author3, { name: 'God2' });
expect(res2).not.toBeNull();
await orm.em.transactional(async em => {
const god3 = new Author3('God3', 'hello@heaven3.god');
await em.persist(god3);
});
const res3 = await orm.em.findOne(Author3, { name: 'God3' });
expect(res3).not.toBeNull();
const err = new Error('Test');
try {
await orm.em.transactional(async em => {
const god4 = new Author3('God4', 'hello@heaven4.god');
await em.persist(god4);
throw err;
});
} catch (e) {
expect(e).toBe(err);
const res4 = await orm.em.findOne(Author3, { name: 'God4' });
expect(res4).toBeNull();
}
});
test('nested transactions with save-points', async () => {
await orm.em.transactional(async em => {
const driver = em.getDriver();
const god1 = new Author3('God1', 'hello@heaven1.god');
await driver.beginTransaction();
await em.persist(god1);
await driver.rollback();
const res1 = await em.findOne(Author3, { name: 'God1' });
expect(res1).toBeNull();
await driver.beginTransaction();
const god2 = new Author3('God2', 'hello@heaven2.god');
await em.persist(god2);
await driver.commit();
const res2 = await em.findOne(Author3, { name: 'God2' });
expect(res2).not.toBeNull();
});
});
test('nested transaction rollback with save-points will commit the outer one', async () => {
const mock = jest.fn();
const logger = new Logger(mock, true);
Object.assign(orm.em.getConnection(), { logger });
// start outer transaction
const transaction = orm.em.transactional(async em => {
// do stuff inside inner transaction and rollback
await em.beginTransaction();
await em.persist(new Author3('God', 'hello@heaven.god'));
await em.rollback();
await em.persist(new Author3('God Persisted!', 'hello-persisted@heaven.god'));
});
// try to commit the outer transaction
await expect(transaction).resolves.toBeUndefined();
expect(mock.mock.calls.length).toBe(6);
expect(mock.mock.calls[0][0]).toMatch('[query-logger] BEGIN');
expect(mock.mock.calls[5][0]).toMatch('[query-logger] COMMIT');
expect(await orm.em.findOne(Author3, { name: 'God Persisted!' })).not.toBeNull();
});
test('should load entities', async () => {
expect(orm).toBeInstanceOf(MikroORM);
expect(orm.em).toBeInstanceOf(EntityManager);
const god = new Author3('God', 'hello@heaven.god');
const bible = new Book3('Bible', god);
await orm.em.persist(bible);
const author = new Author3('Jon Snow', 'snow@wall.st');
author.born = new Date();
author.favouriteBook = bible;
const publisher = new Publisher3('7K publisher', 'global');
const book1 = new Book3('My Life on The Wall, part 1', author);
book1.publisher = publisher;
const book2 = new Book3('My Life on The Wall, part 2', author);
book2.publisher = publisher;
const book3 = new Book3('My Life on The Wall, part 3', author);
book3.publisher = publisher;
const repo = orm.em.getRepository(Book3);
await repo.persist(book1, false);
await repo.persist(book2, false);
await repo.persist(book3, false);
await repo.flush();
orm.em.clear();
const publisher7k = (await orm.em.getRepository<any>(Publisher3).findOne({ name: '7K publisher' }))!;
expect(publisher7k).not.toBeNull();
expect(publisher7k.tests).toBeInstanceOf(Collection);
expect(publisher7k.tests.isInitialized()).toBe(false);
orm.em.clear();
const authorRepository = orm.em.getRepository<any>(Author3);
const booksRepository = orm.em.getRepository<any>(Book3);
const books = await booksRepository.findAll(['author']);
expect(books[0].author.isInitialized()).toBe(true);
expect(await authorRepository.findOne({ favouriteBook: bible.id })).not.toBe(null);
orm.em.clear();
const noBooks = await booksRepository.find({ title: 'not existing' }, ['author']);
expect(noBooks.length).toBe(0);
orm.em.clear();
const jon = (await authorRepository.findOne({ name: 'Jon Snow' }, ['books', 'favouriteBook']))!;
const authors = await authorRepository.findAll(['books', 'favouriteBook']);
expect(await authorRepository.findOne({ email: 'not existing' })).toBeNull();
// count test
const count = await authorRepository.count();
expect(count).toBe(authors.length);
// identity map test
authors.shift(); // shift the god away, as that entity is detached from IM
expect(jon).toBe(authors[0]);
expect(jon).toBe(await authorRepository.findOne(jon.id));
// serialization test
const o = jon.toJSON();
expect(o).toMatchObject({
id: jon.id,
createdAt: jon.createdAt,
updatedAt: jon.updatedAt,
books: [
{ author: jon.id, publisher: publisher.id, title: 'My Life on The Wall, part 1' },
{ author: jon.id, publisher: publisher.id, title: 'My Life on The Wall, part 2' },
{ author: jon.id, publisher: publisher.id, title: 'My Life on The Wall, part 3' },
],
favouriteBook: { author: god.id, title: 'Bible' },
born: jon.born,
email: 'snow@wall.st',
name: 'Jon Snow',
});
expect(jon.toJSON()).toEqual(o);
expect(jon.books.getIdentifiers()).toBeInstanceOf(Array);
expect(typeof jon.books.getIdentifiers()[0]).toBe('number');
for (const author of authors) {
expect(author.books).toBeInstanceOf(Collection);
expect(author.books.isInitialized()).toBe(true);
// iterator test
for (const book of author.books) {
expect(book.title).toMatch(/My Life on The Wall, part \d/);
expect(book.author).toBeInstanceOf(Author3);
expect(book.author.isInitialized()).toBe(true);
expect(book.publisher).toBeInstanceOf(Publisher3);
expect(book.publisher.isInitialized()).toBe(false);
}
}
const booksByTitleAsc = await booksRepository.find({ author: jon.id }, [], { title: 1 });
expect(booksByTitleAsc[0].title).toBe('My Life on The Wall, part 1');
expect(booksByTitleAsc[1].title).toBe('My Life on The Wall, part 2');
expect(booksByTitleAsc[2].title).toBe('My Life on The Wall, part 3');
const booksByTitleDesc = await booksRepository.find({ author: jon.id }, [], { title: -1 });
expect(booksByTitleDesc[0].title).toBe('My Life on The Wall, part 3');
expect(booksByTitleDesc[1].title).toBe('My Life on The Wall, part 2');
expect(booksByTitleDesc[2].title).toBe('My Life on The Wall, part 1');
const twoBooks = await booksRepository.find({ author: jon.id }, [], { title: -1 }, 2);
expect(twoBooks.length).toBe(2);
expect(twoBooks[0].title).toBe('My Life on The Wall, part 3');
expect(twoBooks[1].title).toBe('My Life on The Wall, part 2');
const lastBook = await booksRepository.find({ author: jon.id }, ['author'], { title: -1 }, 2, 2);
expect(lastBook.length).toBe(1);
expect(lastBook[0].title).toBe('My Life on The Wall, part 1');
expect(lastBook[0].author).toBeInstanceOf(Author3);
expect(lastBook[0].author.isInitialized()).toBe(true);
await orm.em.getRepository(Book3).remove(lastBook[0].id);
});
test('findOne should initialize entity that is already in IM', async () => {
const god = new Author3('God', 'hello@heaven.god');
const bible = new Book3('Bible', god);
await orm.em.persist(bible);
orm.em.clear();
const ref = orm.em.getReference(Author3, god.id);
expect(ref.isInitialized()).toBe(false);
const newGod = await orm.em.findOne(Author3, god.id);
expect(ref).toBe(newGod);
expect(ref.isInitialized()).toBe(true);
});
test('findOne supports regexps', async () => {
const author1 = new Author3('Author 1', 'a1@example.com');
const author2 = new Author3('Author 2', 'a2@example.com');
const author3 = new Author3('Author 3', 'a3@example.com');
await orm.em.persist([author1, author2, author3]);
orm.em.clear();
const authors = await orm.em.find<any>(Author3, { email: /exa.*le\.c.m$/ });
expect(authors.length).toBe(3);
expect(authors[0].name).toBe('Author 1');
expect(authors[1].name).toBe('Author 2');
expect(authors[2].name).toBe('Author 3');
});
test('stable results of serialization', async () => {
const god = new Author3('God', 'hello@heaven.god');
const bible = new Book3('Bible', god);
const bible2 = new Book3('Bible pt. 2', god);
const bible3 = new Book3('Bible pt. 3', new Author3('Lol', 'lol@lol.lol'));
await orm.em.persist([bible, bible2, bible3]);
orm.em.clear();
const newGod = (await orm.em.findOne<any>(Author3, god.id))!;
const books = await orm.em.find<any>(Book3, {});
await newGod.init(false);
for (const book of books) {
expect(book.toJSON()).toMatchObject({
author: book.author.id,
});
}
});
test('stable results of serialization (collection)', async () => {
const pub = new Publisher3('Publisher3');
await orm.em.persist(pub);
const god = new Author3('God', 'hello@heaven.god');
const bible = new Book3('Bible', god);
bible.publisher = pub;
const bible2 = new Book3('Bible pt. 2', god);
bible2.publisher = pub;
const bible3 = new Book3('Bible pt. 3', new Author3('Lol', 'lol@lol.lol'));
bible3.publisher = pub;
await orm.em.persist([bible, bible2, bible3]);
orm.em.clear();
const newGod = orm.em.getReference<any>(Author3, god.id);
const publisher = (await orm.em.findOne<any>(Publisher3, pub.id, ['books']))!;
await newGod.init();
const json = publisher.toJSON().books;
for (const book of publisher.books) {
expect(json.find((b: any) => b.id === book.id)).toMatchObject({
author: book.author.id,
});
}
});
test('findOne by id', async () => {
const authorRepository = orm.em.getRepository<any>(Author3);
const jon = new Author3('Jon Snow', 'snow@wall.st');
await authorRepository.persist(jon);
orm.em.clear();
let author = (await authorRepository.findOne(jon.id))!;
expect(author).not.toBeNull();
expect(author.name).toBe('Jon Snow');
orm.em.clear();
author = (await authorRepository.findOne({ id: jon.id }))!;
expect(author).not.toBeNull();
expect(author.name).toBe('Jon Snow');
});
test('populate ManyToOne relation', async () => {
const authorRepository = orm.em.getRepository(Author3);
const god = new Author3('God', 'hello@heaven.god');
const bible = new Book3('Bible', god);
await orm.em.persist(bible);
let jon = new Author3('Jon Snow', 'snow@wall.st');
jon.born = new Date();
jon.favouriteBook = bible;
await orm.em.persist(jon);
orm.em.clear();
jon = (await authorRepository.findOne(jon.id))!;
expect(jon).not.toBeNull();
expect(jon.name).toBe('Jon Snow');
expect(jon.favouriteBook).toBeInstanceOf(Book3);
expect(jon.favouriteBook.isInitialized()).toBe(false);
await jon.favouriteBook.init();
expect(jon.favouriteBook).toBeInstanceOf(Book3);
expect(jon.favouriteBook.isInitialized()).toBe(true);
expect(jon.favouriteBook.title).toBe('Bible');
});
test('many to many relation', async () => {
const author = new Author3('Jon Snow', 'snow@wall.st');
const book1 = new Book3('My Life on The Wall, part 1', author);
const book2 = new Book3('My Life on The Wall, part 2', author);
const book3 = new Book3('My Life on The Wall, part 3', author);
const tag1 = new BookTag3('silly');
const tag2 = new BookTag3('funny');
const tag3 = new BookTag3('sick');
const tag4 = new BookTag3('strange');
const tag5 = new BookTag3('sexy');
book1.tags.add(tag1, tag3);
book2.tags.add(tag1, tag2, tag5);
book3.tags.add(tag2, tag4, tag5);
await orm.em.persist(book1, false);
await orm.em.persist(book2, false);
await orm.em.persist(book3);
expect(tag1.id).toBeDefined();
expect(tag2.id).toBeDefined();
expect(tag3.id).toBeDefined();
expect(tag4.id).toBeDefined();
expect(tag5.id).toBeDefined();
// test inverse side
const tagRepository = orm.em.getRepository<typeof BookTag3>(BookTag3);
let tags = await tagRepository.findAll();
expect(tags).toBeInstanceOf(Array);
expect(tags.length).toBe(5);
expect(tags[0]).toBeInstanceOf(BookTag3);
expect(tags[0].name).toBe('silly');
expect(tags[0].books).toBeInstanceOf(Collection);
expect(tags[0].books.isInitialized()).toBe(true);
expect(tags[0].books.isDirty()).toBe(false);
expect(tags[0].books.count()).toBe(2);
expect(tags[0].books.length).toBe(2);
orm.em.clear();
tags = await orm.em.find(BookTag3);
expect(tags[0].books.isInitialized()).toBe(false);
expect(tags[0].books.isDirty()).toBe(false);
expect(() => tags[0].books.getItems()).toThrowError(/Collection Book3\[] of entity BookTag3\[\d+] not initialized/);
expect(() => tags[0].books.add(book1)).toThrowError(/Collection Book3\[] of entity BookTag3\[\d+] not initialized/);
expect(() => tags[0].books.remove(book1, book2)).toThrowError(/Collection Book3\[] of entity BookTag3\[\d+] not initialized/);
expect(() => tags[0].books.removeAll()).toThrowError(/Collection Book3\[] of entity BookTag3\[\d+] not initialized/);
expect(() => tags[0].books.contains(book1)).toThrowError(/Collection Book3\[] of entity BookTag3\[\d+] not initialized/);
// test M:N lazy init
orm.em.clear();
tags = await tagRepository.findAll();
await tags[0].books.init();
expect(tags[0].books.count()).toBe(2);
expect(tags[0].books.getItems()[0]).toBeInstanceOf(Book3);
expect(tags[0].books.getItems()[0].id).toBeDefined();
expect(tags[0].books.getItems()[0].isInitialized()).toBe(true);
expect(tags[0].books.isInitialized()).toBe(true);
const old = tags[0];
expect(tags[1].books.isInitialized()).toBe(false);
tags = await tagRepository.findAll(['books']);
expect(tags[1].books.isInitialized()).toBe(true);
expect(tags[0].id).toBe(old.id);
expect(tags[0]).toBe(old);
expect(tags[0].books).toBe(old.books);
// test M:N lazy init
orm.em.clear();
let book = (await orm.em.findOne<any>(Book3, { tags: tag1.id }))!;
expect(book.tags.isInitialized()).toBe(false);
await book.tags.init();
expect(book.tags.isInitialized()).toBe(true);
expect(book.tags.count()).toBe(2);
expect(book.tags.getItems()[0]).toBeInstanceOf(BookTag3);
expect(book.tags.getItems()[0].id).toBeDefined();
expect(book.tags.getItems()[0].isInitialized()).toBe(true);
// test collection CRUD
// remove
expect(book.tags.count()).toBe(2);
book.tags.remove(tag1);
await orm.em.persist(book);
orm.em.clear();
book = (await orm.em.findOne(Book3, book.id, ['tags']))!;
expect(book.tags.count()).toBe(1);
// add
book.tags.add(tagRepository.getReference(tag1.id)); // we need to get reference as tag1 is detached from current EM
await orm.em.persist(book);
orm.em.clear();
book = (await orm.em.findOne(Book3, book.id, ['tags']))!;
expect(book.tags.count()).toBe(2);
// contains
expect(book.tags.contains(tag1)).toBe(true);
expect(book.tags.contains(tag2)).toBe(false);
expect(book.tags.contains(tag3)).toBe(true);
expect(book.tags.contains(tag4)).toBe(false);
expect(book.tags.contains(tag5)).toBe(false);
// removeAll
book.tags.removeAll();
await orm.em.persist(book);
orm.em.clear();
book = (await orm.em.findOne(Book3, book.id, ['tags']))!;
expect(book.tags.count()).toBe(0);
});
test('populating many to many relation', async () => {
const p1 = new Publisher3('foo');
expect(p1.tests).toBeInstanceOf(Collection);
expect(p1.tests.isInitialized()).toBe(true);
expect(p1.tests.isDirty()).toBe(false);
expect(p1.tests.count()).toBe(0);
const p2 = new Publisher3('bar');
p2.tests.add(new Test3(), new Test3());
await orm.em.persist([p1, p2]);
const repo = orm.em.getRepository<any>(Publisher3);
orm.em.clear();
const publishers = await repo.findAll(['tests']);
expect(publishers).toBeInstanceOf(Array);
expect(publishers.length).toBe(2);
expect(publishers[0]).toBeInstanceOf(Publisher3);
expect(publishers[0].tests).toBeInstanceOf(Collection);
expect(publishers[0].tests.isInitialized()).toBe(true);
expect(publishers[0].tests.isDirty()).toBe(false);
expect(publishers[0].tests.count()).toBe(0);
await publishers[0].tests.init(); // empty many to many on owning side should not make db calls
expect(publishers[1].tests.getItems()[0].isInitialized()).toBe(true);
});
test('populating many to many relation on inverse side', async () => {
const author = new Author3('Jon Snow', 'snow@wall.st');
const book1 = new Book3('My Life on The Wall, part 1', author);
const book2 = new Book3('My Life on The Wall, part 2', author);
const book3 = new Book3('My Life on The Wall, part 3', author);
const tag1 = new BookTag3('silly');
const tag2 = new BookTag3('funny');
const tag3 = new BookTag3('sick');
const tag4 = new BookTag3('strange');
const tag5 = new BookTag3('sexy');
book1.tags.add(tag1, tag3);
book2.tags.add(tag1, tag2, tag5);
book3.tags.add(tag2, tag4, tag5);
await orm.em.persist([book1, book2, book3]);
const repo = orm.em.getRepository<any>(BookTag3);
orm.em.clear();
const tags = await repo.findAll(['books']);
expect(tags).toBeInstanceOf(Array);
expect(tags.length).toBe(5);
expect(tags[0]).toBeInstanceOf(BookTag3);
expect(tags[0].books).toBeInstanceOf(Collection);
expect(tags[0].books.isInitialized()).toBe(true);
expect(tags[0].books.isDirty()).toBe(false);
expect(tags[0].books.count()).toBe(2);
expect(tags[0].books.getItems()[0].isInitialized()).toBe(true);
});
test('hooks', async () => {
Author3.beforeDestroyCalled = 0;
Author3.afterDestroyCalled = 0;
const repo = orm.em.getRepository(Author3);
const author = new Author3('Jon Snow', 'snow@wall.st');
expect(author.id).toBeUndefined();
expect(author.version).toBeUndefined();
expect(author.versionAsString).toBeUndefined();
await repo.persist(author);
expect(author.id).toBeDefined();
expect(author.version).toBe(1);
expect(author.versionAsString).toBe('v1');
author.name = 'John Snow';
await repo.persist(author);
expect(author.version).toBe(2);
expect(author.versionAsString).toBe('v2');
expect(Author3.beforeDestroyCalled).toBe(0);
expect(Author3.afterDestroyCalled).toBe(0);
await repo.remove(author);
expect(Author3.beforeDestroyCalled).toBe(1);
expect(Author3.afterDestroyCalled).toBe(1);
const author2 = new Author3('Johny Cash', 'johny@cash.com');
await repo.persist(author2);
await repo.remove(author2);
expect(Author3.beforeDestroyCalled).toBe(2);
expect(Author3.afterDestroyCalled).toBe(2);
});
test('trying to populate non-existing or non-reference property will throw', async () => {
const repo = orm.em.getRepository(Author3);
const author = new Author3('Johny Cash', 'johny@cash.com');
await repo.persist(author);
orm.em.clear();
await expect(repo.findAll(['tests'])).rejects.toThrowError(`Entity 'Author3' does not have property 'tests'`);
await expect(repo.findOne(author.id, ['tests'])).rejects.toThrowError(`Entity 'Author3' does not have property 'tests'`);
});
test('many to many collection does have fixed order', async () => {
const repo = orm.em.getRepository<any>(Publisher3);
const publisher = new Publisher3();
const t1 = Test3.create('t1');
const t2 = Test3.create('t2');
const t3 = Test3.create('t3');
await orm.em.persist([t1, t2, t3]);
publisher.tests.add(t2, t1, t3);
await repo.persist(publisher);
orm.em.clear();
const ent = (await repo.findOne(publisher.id, ['tests']))!;
await expect(ent.tests.count()).toBe(3);
await expect(ent.tests.getIdentifiers()).toEqual([t2.id, t1.id, t3.id]);
await ent.tests.init();
await expect(ent.tests.getIdentifiers()).toEqual([t2.id, t1.id, t3.id]);
});
test('property onUpdate hook (updatedAt field)', async () => {
const repo = orm.em.getRepository<any>(Author3);
const author = new Author3('name', 'email');
await expect(author.createdAt).toBeDefined();
await expect(author.updatedAt).toBeDefined();
// allow 1 ms difference as updated time is recalculated when persisting
await expect(+author.updatedAt - +author.createdAt).toBeLessThanOrEqual(1);
await repo.persist(author);
author.name = 'name1';
await new Promise(resolve => setTimeout(resolve, 10));
await repo.persist(author);
await expect(author.createdAt).toBeDefined();
await expect(author.updatedAt).toBeDefined();
await expect(author.updatedAt).not.toEqual(author.createdAt);
await expect(author.updatedAt > author.createdAt).toBe(true);
orm.em.clear();
const ent = (await repo.findOne(author.id))!;
await expect(ent.createdAt).toBeDefined();
await expect(ent.updatedAt).toBeDefined();
await expect(ent.updatedAt).not.toEqual(ent.createdAt);
await expect(ent.updatedAt > ent.createdAt).toBe(true);
});
test('EM supports native insert/update/delete', async () => {
orm.config.getLogger().setDebugMode(false);
const res1 = await orm.em.nativeInsert(Author3, { name: 'native name 1', email: 'native1@email.com' });
expect(typeof res1).toBe('number');
const res2 = await orm.em.nativeUpdate(Author3, { name: 'native name 1' }, { name: 'new native name' });
expect(res2).toBe(1);
const res3 = await orm.em.nativeDelete(Author3, { name: 'new native name' });
expect(res3).toBe(1);
const res4 = await orm.em.nativeInsert(Author3, { createdAt: new Date('1989-11-17'), updatedAt: new Date('2018-10-28'), name: 'native name 2', email: 'native2@email.com' });
expect(typeof res4).toBe('number');
const res5 = await orm.em.nativeUpdate(Author3, { name: 'native name 2' }, { name: 'new native name', updatedAt: new Date('2018-10-28') });
expect(res5).toBe(1);
await expect(orm.em.aggregate(Author3, [])).rejects.toThrowError('Aggregations are not supported by SqliteDriver driver');
});
test('Utils.prepareEntity changes entity to number id', async () => {
const author1 = new Author3('Name 1', 'e-mail1');
const book = new Book3('test', author1);
const author2 = new Author3('Name 2', 'e-mail2');
author2.favouriteBook = book;
author2.version = 123;
await orm.em.persist([author1, author2, book]);
const diff = Utils.diffEntities(author1, author2);
expect(diff).toMatchObject({ name: 'Name 2', favouriteBook: book.id });
expect(typeof diff.favouriteBook).toBe('number');
});
test('EM supports smart search conditions', async () => {
const author = new Author3('name', 'email');
const b1 = new Book3('b1', author);
const b2 = new Book3('b2', author);
const b3 = new Book3('b3', author);
await orm.em.persist([b1, b2, b3]);
orm.em.clear();
const a1 = (await orm.em.findOne(Author3, { 'id:ne': 10 }))!;
expect(a1).not.toBeNull();
expect(a1.id).toBe(author.id);
const a2 = (await orm.em.findOne(Author3, { 'id>=': 1 }))!;
expect(a2).not.toBeNull();
expect(a2.id).toBe(author.id);
const a3 = (await orm.em.findOne(Author3, { 'id:nin': [2, 3, 4] }))!;
expect(a3).not.toBeNull();
expect(a3.id).toBe(author.id);
const a4 = (await orm.em.findOne(Author3, { 'id:in': [] }))!;
expect(a4).toBeNull();
const a5 = (await orm.em.findOne(Author3, { 'id:nin': [] }))!;
expect(a5).not.toBeNull();
expect(a5.id).toBe(author.id);
});
afterAll(async () => {
await orm.close(true);
unlinkSync(orm.config.get('dbName'));
});
});