From 76811dd0b88dee6b5659b98bbde2acba4619123a Mon Sep 17 00:00:00 2001 From: Alice Gaudon Date: Wed, 5 Aug 2020 10:45:13 +0200 Subject: [PATCH] Add more tests for Model --- src/db/Model.ts | 16 +++--- test/Model.test.ts | 129 +++++++++++++++++++++++++++++++++------------ 2 files changed, 104 insertions(+), 41 deletions(-) diff --git a/src/db/Model.ts b/src/db/Model.ts index 3488f83..b1a291a 100644 --- a/src/db/Model.ts +++ b/src/db/Model.ts @@ -160,14 +160,6 @@ export default abstract class Model { return needs_full_update; } - public async exists(): Promise { - let query = this._factory.select('1'); - for (const indexField of this._factory.getPrimaryKeyFields()) { - query = query.where(indexField, this[indexField]); - } - return (await query.limit(1).execute()).results.length > 0; - } - public async delete(): Promise { if (!(await this.exists())) throw new Error('This model instance doesn\'t exist in DB.'); @@ -178,6 +170,14 @@ export default abstract class Model { await query.execute(); } + public async exists(): Promise { + let query = this._factory.select('1'); + for (const indexField of this._factory.getPrimaryKeyFields()) { + query = query.where(indexField, this[indexField]); + } + return (await query.limit(1).execute()).results.length > 0; + } + public async validate(onlyFormat: boolean = false, connection?: Connection): Promise { return await Promise.all(this._properties.map( prop => this._validators[prop]?.execute(prop, this[prop], onlyFormat, connection) diff --git a/test/Model.test.ts b/test/Model.test.ts index 53bcb60..c77a830 100644 --- a/test/Model.test.ts +++ b/test/Model.test.ts @@ -2,6 +2,7 @@ import MysqlConnectionManager from "../src/db/MysqlConnectionManager"; import Model from "../src/db/Model"; import {MIGRATIONS} from "./_migrations"; import ModelFactory from "../src/db/ModelFactory"; +import {ValidationBag, ValidationError} from "../src/db/Validator"; class FakeDummyModel extends Model { public id?: number = undefined; @@ -14,54 +15,116 @@ class FakeDummyModel extends Model { } } -beforeAll(async (done) => { +let factory: ModelFactory; + +beforeAll(async () => { MysqlConnectionManager.registerMigrations(MIGRATIONS); ModelFactory.register(FakeDummyModel); await MysqlConnectionManager.prepare(); - done(); -}); -afterAll(async (done) => { - await MysqlConnectionManager.endPool(); - done(); -}); - -describe('Model', () => { - it('should have a proper table name', async () => { - const factory = ModelFactory.get(FakeDummyModel); - expect(factory.table).toBe('fake_dummy_models'); - expect(FakeDummyModel.create({}).table).toBe('fake_dummy_models'); - }); - - it('should insert and retrieve properly', async () => { - const factory = ModelFactory.get(FakeDummyModel); - await MysqlConnectionManager.query(`DROP TABLE IF EXISTS ${(factory.table)}`); - await MysqlConnectionManager.query(`CREATE TABLE ${(factory.table)}( + // Create FakeDummyModel table + factory = ModelFactory.get(FakeDummyModel); + await MysqlConnectionManager.query(`DROP TABLE IF EXISTS ${(factory.table)}`); + await MysqlConnectionManager.query(`CREATE TABLE ${(factory.table)}( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(256), date DATETIME, date_default DATETIME DEFAULT NOW(), PRIMARY KEY(id) )`); +}); +afterAll(async () => { + await MysqlConnectionManager.endPool(); +}); + +describe('Model', () => { + it('should construct properly', () => { + const date = new Date(888); + const model = factory.create({ + name: 'a_name', + date: date, + non_existing_property: 'dropped_value', + }); + + expect(model.id).toBeUndefined(); + expect(model.name).toBe('a_name'); + expect(model.date).toBe(date); + expect(model.date_default).toBeUndefined(); + expect(model.non_existing_property).toBeUndefined(); + }); + + it('should have a proper table name', () => { + expect(factory.table).toBe('fake_dummy_models'); + expect(FakeDummyModel.table).toBe('fake_dummy_models'); + expect(FakeDummyModel.create({}).table).toBe('fake_dummy_models'); + }); + + it('should insert properly', async () => { const date = new Date(569985); - let instance: FakeDummyModel | null = FakeDummyModel.create({ + const insertInstance: FakeDummyModel | null = factory.create({ name: 'name1', date: date, }); - console.log(instance) - await instance.save(); - expect(instance.id).toBe(1); - expect(instance.name).toBe('name1'); - expect(instance.date?.getTime()).toBeCloseTo(date.getTime(), -4); - expect(instance.date_default).toBeDefined(); - instance = await FakeDummyModel.getById(1); - expect(instance).toBeDefined(); - expect(instance!.id).toBe(1); - expect(instance!.name).toBe('name1'); - expect(instance!.date?.getTime()).toBeCloseTo(date.getTime(), -4); - expect(instance!.date_default).toBeDefined(); - }, 15000); + // Insert + expect(await insertInstance.exists()).toBeFalsy(); + await insertInstance.save(); + expect(await insertInstance.exists()).toBeTruthy(); + + expect(insertInstance.id).toBe(1); // Auto id from insert + expect(insertInstance.name).toBe('name1'); + expect(insertInstance.date?.getTime()).toBeCloseTo(date.getTime(), -4); + expect(insertInstance.date_default).toBeDefined(); + + // Check that row exists in DB + const retrievedInstance = await FakeDummyModel.getById(1); + expect(retrievedInstance).toBeDefined(); + expect(retrievedInstance!.id).toBe(1); + expect(retrievedInstance!.name).toBe('name1'); + expect(retrievedInstance!.date?.getTime()).toBeCloseTo(date.getTime(), -4); + expect(retrievedInstance!.date_default).toBeDefined(); + + const failingInsertModel = factory.create({ + name: 'a', + }); + await expect(failingInsertModel.save()).rejects.toBeInstanceOf(ValidationBag); + }); + + it('should update properly', async () => { + const insertModel = factory.create({ + name: 'update', + }); + await insertModel.save(); + + const preUpdatedModel = await FakeDummyModel.getById(insertModel.id); + expect(preUpdatedModel).not.toBeNull(); + expect(preUpdatedModel!.name).toBe(insertModel.name); + + // Update model + preUpdatedModel!.name = 'updated_name'; + await preUpdatedModel!.save(); + + const postUpdatedModel = await FakeDummyModel.getById(insertModel.id); + expect(postUpdatedModel).not.toBeNull(); + expect(postUpdatedModel!.id).toBe(insertModel.id); + expect(postUpdatedModel!.name).not.toBe(insertModel.name); + expect(postUpdatedModel!.name).toBe(preUpdatedModel!.name); + }); + + it('should delete properly', async () => { + const insertModel = factory.create({ + name: 'delete', + }); + await insertModel.save(); + + const preDeleteModel = await FakeDummyModel.getById(insertModel.id); + expect(preDeleteModel).not.toBeNull(); + + await preDeleteModel!.delete(); + + const postDeleteModel = await FakeDummyModel.getById(insertModel.id); + expect(postDeleteModel).toBeNull(); + }); }); \ No newline at end of file