diff --git a/integration/test/features/EloquentQuery.test.ts b/integration/test/features/EloquentQuery.test.ts index e524cdb..a3aa4a6 100644 --- a/integration/test/features/EloquentQuery.test.ts +++ b/integration/test/features/EloquentQuery.test.ts @@ -1,19 +1,20 @@ +import { NotFoundError } from '../../../dist/lib/errors/NotFoundError' import { QueryLog, factory } from '../../../dist/lib' import { User, init_mongoose, delete_collection } from '../../mongodb/index' -describe('Integration Test - Eloquent (1st way) querying', function() { - beforeAll(async function() { +describe('Integration Test - Eloquent (1st way) querying', function () { + beforeAll(async function () { await init_mongoose('integration_eloquent_query') }) - afterEach(async function() { + afterEach(async function () { await delete_collection(['users']) }) const userModel = new User() - describe('.queryName()', function() { - it('starts new query with given name.', async function() { + describe('.queryName()', function () { + it('starts new query with given name.', async function () { const query = userModel.queryName('You can name the query what ever you want') expect(query['queryBuilder']['name']).toEqual('You can name the query what ever you want') @@ -25,8 +26,8 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.select()', function() { - it('set the columns or fields to be selected.', async function() { + describe('.select()', function () { + it('set the columns or fields to be selected.', async function () { await factory(User).create() const users = await userModel.select('email', 'password').get() for (const user of users) { @@ -37,21 +38,21 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.orderBy()', function() { - it('adds an "order by" clause to the query.', async function() { + describe('.orderBy()', function () { + it('adds an "order by" clause to the query.', async function () { await factory(User).create({ age: 50, first_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c' }) expect( (await userModel.orderBy('age').get()) - .map(function(user) { + .map(function (user) { return user.first_name }) .toArray() ).toEqual(['c', 'b', 'a']) expect( (await userModel.orderBy('age', 'desc').get()) - .map(function(user) { + .map(function (user) { return user.first_name }) .toArray() @@ -59,21 +60,21 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.orderByAsc()', function() { - it('adds an "order by" clause to the query with direction ASC.', async function() { + describe('.orderByAsc()', function () { + it('adds an "order by" clause to the query with direction ASC.', async function () { await factory(User).create({ age: 50, first_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c' }) expect( (await userModel.orderByAsc('age').get()) - .map(function(user) { + .map(function (user) { return user.first_name }) .toArray() ).toEqual(['c', 'b', 'a']) expect( (await userModel.orderByAsc('first_name').get()) - .map(function(user) { + .map(function (user) { return user.first_name }) .toArray() @@ -81,21 +82,21 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.orderByDesc()', function() { - it('adds an "order by" clause to the query with direction DESC.', async function() { + describe('.orderByDesc()', function () { + it('adds an "order by" clause to the query with direction DESC.', async function () { await factory(User).create({ age: 50, first_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c' }) expect( (await userModel.orderByDesc('age').get()) - .map(function(user) { + .map(function (user) { return user.first_name }) .toArray() ).toEqual(['a', 'b', 'c']) expect( (await userModel.orderByDesc('first_name').get()) - .map(function(user) { + .map(function (user) { return user.first_name }) .toArray() @@ -103,8 +104,8 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.limit()', function() { - it('adds an "order by" clause to the query with direction DESC.', async function() { + describe('.limit()', function () { + it('adds an "order by" clause to the query with direction DESC.', async function () { await factory(User).create({ age: 50, first_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c' }) @@ -113,7 +114,7 @@ describe('Integration Test - Eloquent (1st way) querying', function() { .orderByDesc('age') .limit(2) .get()) - .map(function(user) { + .map(function (user) { return user.first_name }) .toArray() @@ -123,7 +124,7 @@ describe('Integration Test - Eloquent (1st way) querying', function() { .orderByDesc('first_name') .limit(1) .get()) - .map(function(user) { + .map(function (user) { return user.first_name }) .toArray() @@ -131,14 +132,14 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.where()', function() { - it('adds a basic where clause to the query.', async function() { + describe('.where()', function () { + it('adds a basic where clause to the query.', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) const result = await userModel .where('age', '>', 10) - .where(function(query) { + .where(function (query) { return query.where('first_name', 'a').orWhere('first_name', 'b') }) .pluck('first_name', 'age') @@ -146,14 +147,14 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.orWhere()', function() { - it('adds an "or where" clause to the query.', async function() { + describe('.orWhere()', function () { + it('adds an "or where" clause to the query.', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) const result = await userModel .where('age', 40) - .orWhere(function(query) { + .orWhere(function (query) { return query.where('first_name', 'a').orWhere('first_name', 'b') }) .pluck('first_name', 'age') @@ -161,8 +162,21 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.whereIn()', function() { - it('adds a "where in" clause to the query.', async function() { + describe('.andWhere()', function () { + it('add an "and where" clause to query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel + .where('age', '>', 35) + .andWhere('first_name', 'a') + .pluck('first_name', 'age') + expect(result).toEqual({ 50: 'a' }) + }) + }) + + describe('.whereIn()', function () { + it('adds a "where in" clause to the query.', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) @@ -171,8 +185,8 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.orWhereIn()', function() { - it('adds an "or where in" clause to the query.', async function() { + describe('.orWhereIn()', function () { + it('adds an "or where in" clause to the query.', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) @@ -184,8 +198,31 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.orWhereNotIn()', function() { - it('adds an "or where not in" clause to the query.', async function() { + describe('.andWhereIn()', function () { + it('adds an " and where in" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel + .where('age', '>', 20) + .andWhereIn('first_name', ['a', 'c']) + .pluck('first_name', 'age') + expect(result).toEqual({ 50: 'a', 30: 'c' }) + }) + }) + + describe('.whereNotIn()', function () { + it('adds a "where not in" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel.whereNotIn('age', [30, 40]).pluck('first_name', 'age') + expect(result).toEqual({ 50: 'a' }) + }) + }) + + describe('.orWhereNotIn()', function () { + it('adds an "or where not in" clause to the query.', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) @@ -197,8 +234,21 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.whereNull()', function() { - it('adds a "where null" clause to the query.', async function() { + describe('.andWhereNotIn()', function () { + it('adds an "and where not in" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel + .where('age', '>', 25) + .andWhereNotIn('first_name', ['a', 'c']) + .pluck('first_name', 'age') + expect(result).toEqual({ 40: 'b' }) + }) + }) + + describe('.whereNull()', function () { + it('adds a "where null" clause to the query.', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) // tslint:disable-next-line await factory(User).create({ age: null, first_name: 'b', last_name: 'b' }) @@ -209,8 +259,38 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.whereNotNull()', function() { - it('adds a "where not null" clause to the query.', async function() { + describe('.orWhereNull()', function () { + it('adds an "or where null" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + // tslint:disable-next-line + await factory(User).create({ age: null, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + + const result = await userModel + .where('first_name', 'a') + .orWhereNull('age') + .pluck('first_name', 'last_name') + expect(result).toEqual({ a: 'a', b: 'b' }) + }) + }) + + describe('.andWhereNull()', function () { + it('adds an "and where null" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + // tslint:disable-next-line + await factory(User).create({ age: null, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + + const result = await userModel + .whereIn('first_name', ['a', 'b']) + .andWhereNull('age') + .pluck('first_name', 'last_name') + expect(result).toEqual({ b: 'b' }) + }) + }) + + describe('.whereNotNull()', function () { + it('adds a "where not null" clause to the query.', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) // tslint:disable-next-line await factory(User).create({ age: null, first_name: 'b', last_name: 'b' }) @@ -221,8 +301,8 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.orWhereNotNull()', function() { - it('adds an "or where null" clause to the query.', async function() { + describe('.orWhereNotNull()', function () { + it('adds an "or where null" clause to the query.', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) // tslint:disable-next-line await factory(User).create({ age: null, first_name: 'b', last_name: 'b' }) @@ -236,8 +316,153 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.withTrashed()', function() { - it('considers all soft-deleted or not-deleted items.', async function() { + describe('.andWhereNotNull()', function () { + it('adds an "and where null" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + // tslint:disable-next-line + await factory(User).create({ age: null, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + + const result = await userModel + .whereIn('first_name', ['a', 'b']) + .andWhereNotNull('age') + .pluck('first_name', 'last_name') + expect(result).toEqual({ a: 'a' }) + }) + }) + + describe('.whereBetween()', function () { + it('adds a "where between" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel.whereBetween('age', [35, 50]).pluck('first_name', 'age') + expect(result).toEqual({ 50: 'a', 40: 'b' }) + }) + }) + + describe('.orWhereBetween()', function () { + it('adds an "or where between" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel + .where('first_name', 'c') + .orWhereBetween('age', [45, 50]) + .pluck('first_name', 'age') + expect(result).toEqual({ 50: 'a', 30: 'c' }) + }) + }) + + describe('.andWhereBetween()', function () { + it('adds an "and where between" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel + .whereIn('first_name', ['a', 'b']) + .andWhereBetween('age', [35, 45]) + .pluck('first_name', 'age') + expect(result).toEqual({ 40: 'b' }) + }) + }) + + describe('.whereNot()', function () { + it('adds a "where not" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel.whereNot('first_name', 'a').pluck('first_name', 'last_name') + expect(result).toEqual({ b: 'b', c: 'c' }) + }) + }) + + describe('.orWhereNot()', function () { + it('adds an "or where not" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel + .where('last_name', 'b') + .orWhereNot('first_name', 'a') + .pluck('first_name', 'last_name') + expect(result).toEqual({ b: 'b', c: 'c' }) + }) + }) + + describe('.andWhereNot()', function () { + it('adds an "and where not" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel + .where('age', '>', 35) + .andWhereNot('first_name', 'a') + .pluck('first_name', 'last_name') + expect(result).toEqual({ b: 'b' }) + }) + }) + + describe('.whereNotBetween()', function () { + it('adds a "where not between" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel.whereNotBetween('age', [45, 55]).pluck('first_name', 'last_name') + expect(result).toEqual({ b: 'b', c: 'c' }) + }) + }) + + describe('.orWhereNotBetween()', function () { + it('adds an "or where not between" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel + .where('first_name', 'b') + .orWhereNotBetween('age', [45, 55]) + .pluck('first_name', 'last_name') + expect(result).toEqual({ b: 'b', c: 'c' }) + }) + }) + + describe('.andWhereNotBetween()', function () { + it('adds an "and where not between" clause to the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel + .whereIn('first_name', ['a', 'b']) + .andWhereNotBetween('age', [45, 55]) + .pluck('first_name', 'last_name') + expect(result).toEqual({ b: 'b' }) + }) + }) + + describe('.execute()', function () { + it('can execute clause and return an array', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + const result = await userModel.where('age', '>', 35).execute() + expect(result).toBeInstanceOf(Array) + expect(result.length).toEqual(2) + }) + }) + + describe('.getPrimaryKeyName()', function () { + it('retrieves the "get primary key name" result of the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + + const result = await userModel.where('age', '<', 40).getPrimaryKeyName() + expect(result).toEqual('_id') + }) + }) + + describe('.withTrashed()', function () { + it('considers all soft-deleted or not-deleted items.', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) @@ -254,8 +479,8 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.onlyTrashed()', function() { - it('considers soft-deleted items only.', async function() { + describe('.onlyTrashed()', function () { + it('considers soft-deleted items only.', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) @@ -276,8 +501,8 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.all()', function() { - it('executes the query and return a Collection', async function() { + describe('.all()', function () { + it('executes the query and return a Collection', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) @@ -287,8 +512,8 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.get()', function() { - it('executes the query and return a Collection', async function() { + describe('.get()', function () { + it('executes the query and return a Collection', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) @@ -298,8 +523,8 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.first()', function() { - it('executes the query and return an instance of Model', async function() { + describe('.first()', function () { + it('executes the query and return an instance of Model', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) @@ -312,7 +537,7 @@ describe('Integration Test - Eloquent (1st way) querying', function() { expect(result['first_name']).toEqual('b') }) - it('executes the query and return an instance of Model', async function() { + it('executes the query and return an instance of Model', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) const userB = await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) @@ -322,8 +547,8 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.find()', function() { - it('executes the query and return an instance of Model', async function() { + describe('.find()', function () { + it('executes the query and return an instance of Model', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) @@ -336,7 +561,7 @@ describe('Integration Test - Eloquent (1st way) querying', function() { expect(result['first_name']).toEqual('b') }) - it('executes the query and return an instance of Model', async function() { + it('executes the query and return an instance of Model', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) const userB = await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) @@ -346,8 +571,8 @@ describe('Integration Test - Eloquent (1st way) querying', function() { }) }) - describe('.count()', function() { - it('retrieves the "count" result of the query.', async function() { + describe('.count()', function () { + it('retrieves the "count" result of the query.', async function () { await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) @@ -356,4 +581,128 @@ describe('Integration Test - Eloquent (1st way) querying', function() { expect(result).toEqual(1) }) }) + + describe('.delete()', function () { + it('can delete an item', async function () { + const a = await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + await a.delete() + const result = await userModel.onlyTrashed().pluck('first_name', 'last_name') + expect(result).toEqual({ a: 'a' }) + }) + + // TODO: it don't soft-delete multiple items, waiting for check + // it('can delete multiple items', async function () { + // await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + // await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + // await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + // await userModel.where('view', '>', 35).delete + // const result = await userModel.onlyTrashed().pluck('first_name', 'last_name') + // expect(result).toEqual({ a: 'a', b: 'b' }) + // }) + }) + + describe('.restore()', function () { + it('can restore a soft-deleted item', async function () { + const a = await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + await a.delete() + await a.restore() + const result = (await userModel.get()).pluck('first_name', 'last_name').all() + expect(result).toEqual({ a: 'a', b: 'b', c: 'c' }) + }) + + it('can restore multiple soft-deleted items', async function () { + const a = await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + const b = await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + await a.delete() + await b.delete() + await userModel.onlyTrashed().whereIn('first_name', ['a', 'b']).restore() + const result = (await userModel.get()).pluck('first_name', 'last_name').all() + expect(result).toEqual({ a: 'a', b: 'b', c: 'c' }) + }) + }) + + describe('.update()', function () { + it('retrieves the "update" result of the query.', async function () { + await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + await userModel.where('age', '>', 35).update({ age: 60, first_name: 'updated' }) + const resultFirstNameUpdated = (await userModel.get()).pluck('first_name', 'last_name').all() + const resultAgeUpdated = (await userModel.get()).pluck('age', 'last_name').all() + expect(resultFirstNameUpdated).toEqual({ a: 'updated', b: 'updated', c: 'c' }) + expect(resultAgeUpdated).toEqual({ a: 60, b: 60, c: 30 }) + }) + }) + + describe('.findOrFail()', function () { + it('executes the query and return a Collection', async function () { + const userA = await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + + const result = await userModel.where('age', '>', 35).findOrFail(userA.id) + if (result) { + expect(result.first_name).toEqual('a') + } + }) + + it('executes the query and throws a NotFoundError if result is null', async function () { + const userA = await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + try { + await userModel.where('age', '<', 45).findOrFail(userA.id) + } catch (err) { + expect(err).toBeInstanceOf(NotFoundError) + expect(err.model).toEqual('User') + return + } + expect('should not reach this line').toEqual('hum') + }) + }) + + describe('.firstOrFail()', function () { + it('executes the query and return a Collection', async function () { + const userA = await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + + const result = await userModel.where('age', '>', 35).firstOrFail(userA.id) + if (result) { + expect(result.first_name).toEqual('a') + } + }) + + it('executes the query and throws a NotFoundError if result is null', async function () { + const userA = await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + try { + await userModel.where('age', '<', 45).firstOrFail(userA.id) + } catch (err) { + expect(err).toBeInstanceOf(NotFoundError) + expect(err.model).toEqual('User') + return + } + expect('should not reach this line').toEqual('hum') + }) + }) + + describe('.findById()', function () { + it('executes the query and return a Collection', async function () { + const userA = await factory(User).create({ age: 50, first_name: 'a', last_name: 'a' }) + await factory(User).create({ age: 40, first_name: 'b', last_name: 'b' }) + await factory(User).create({ age: 30, first_name: 'c', last_name: 'c' }) + + const result = await userModel.where('view', '>', 35).findById(userA.id) + if (result) { + expect(result.first_name).toEqual('a') + } + }) + }) }) diff --git a/integration/test/features/Factory.test.ts b/integration/test/features/Factory.test.ts new file mode 100644 index 0000000..1f082ee --- /dev/null +++ b/integration/test/features/Factory.test.ts @@ -0,0 +1,171 @@ +import 'jest' +import { Eloquent, Factory, Faker, factory } from '../../../dist/lib' +import { User, init_mongoose } from '../../mongodb/index' +import * as Validator from 'validator' + +interface ITest { + name: string + status: string + is_test: boolean + created_at: Date + updated_at: Date + deleted_at: Date | null +} + +interface Test extends ITest { } +class Test extends Eloquent { + static className: string = 'Test' + static timestamps = true + static softDeletes = true + static fillable = ['name', 'status', 'is_test'] + static schema = { + name: { type: String, required: true }, + status: { type: String }, + is_test: { type: Boolean } + } + + getClassName() { + return Test.className + } +} + +Factory.define(Test, (faker: Faker, attributes?: Object): Object => { + return Object.assign( + { + name: faker.name() + }, + attributes + ) +}) +Factory.defineAs(Test, 'test', (faker: Faker, attributes?: Object): Object => { + return Object.assign( + { + name: faker.name(), + is_test: true + }, + attributes + ) +}) +Factory.state(Test, 'tested', () => { + return { + status: 'tested' + } +}) +Factory.state(Test, 'testing', () => { + return { + status: 'testing' + } +}) + +function expectUser(user: User) { + expect(Validator.isMongoId(user.id)).toBe(true) + expect(typeof (user.first_name)).toEqual('string') + expect(typeof (user.last_name)).toEqual('string') + expect(Validator.isEmail(user.email)).toBe(true) + expect(user.deleted_at).toBeNull() + expect(typeof (user.age)).toEqual('number') +} + +function expectTest(test: Test) { + expect(Validator.isMongoId(test.id)).toBe(true) + expect(typeof (test.name)).toEqual('string') + expect(test.deleted_at).toBeNull() +} + +describe('Factory', function () { + beforeAll(async function () { + await init_mongoose('integration_factory') + }) + + // afterEach(async function () { + // await delete_collection(['users']) + // }) + + describe('.make()', function () { + it('can make an instance of User', function () { + const testUser = Factory.make(User) + expectUser(testUser) + }) + + it('can make an instance of Test with status is tested', function () { + const test = factory(Test).states(['tested']).make() + expectTest(test) + expect(test.status).toEqual('tested') + }) + + it('can make an instance of Test with status is testing', function () { + const test = factory(Test).states(['testing']).make() + expectTest(test) + expect(test.status).toEqual('testing') + }) + }) + + describe('.makeAs()', function () { + it('can make as an instance of Test', function () { + const test = Factory.makeAs(Test, 'test') + expectTest(test) + expect(test.is_test).toBe(true) + }) + }) + + describe('.create()', function () { + it('can create an instance of User', async function () { + const testUser = await Factory.create(User) + expectUser(testUser) + expect(testUser.created_at instanceof Date).toBe(true) + expect(testUser.updated_at instanceof Date).toBe(true) + }) + + it('can create an instance of Test with status is tested', async function () { + const test = await factory(Test).states(['tested']).create() + expectTest(test) + expect(test.status).toEqual('tested') + expect(test.created_at instanceof Date).toBe(true) + expect(test.updated_at instanceof Date).toBe(true) + }) + + it('can create an instance of Test with status is testing', async function () { + const test = await factory(Test).states(['testing']).create() + expectTest(test) + expect(test.status).toEqual('testing') + expect(test.created_at instanceof Date).toBe(true) + expect(test.updated_at instanceof Date).toBe(true) + }) + + it('can create 5 instance of User', async function () { + const users = await factory(User).times(5).create() + expect(users.count()).toEqual(5) + }) + }) + + describe('.createAs()', function () { + it('can create as an instance of Test', async function () { + const test = await Factory.createAs(Test, 'test') + expectTest(test) + expect(test.created_at instanceof Date).toBe(true) + expect(test.updated_at instanceof Date).toBe(true) + expect(test.is_test).toBe(true) + }) + }) + + describe('.rawOf()', function () { + it('can raw of an instance of Test', function () { + const test = Factory.rawOf(Test, 'test') + expect(test).toMatchObject({ is_test: true }) + }) + }) + + describe('.raw()', function () { + it('can raw an instance of Test', function () { + const test = Factory.raw(Test, { name: 'test' }) + expect(test).toMatchObject({ name: 'test' }) + }) + }) + + describe('.getFacade()', function () { + it('can raw an instance of Test', function () { + const test = Factory.getFacade().createMock() + console.log(test) + }) + }) +}) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 331aa5c..8ce2e94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -102,6 +102,12 @@ "integrity": "sha512-rvgY5bK5ZBRJPuJF0vJI+NC2gt+lakobTa8pnDS/oRH2gk/tooeDEel8piZA8Ng6pxq0A5QGzilIFSyashP6jw==", "dev": true }, + "@types/validator": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-9.4.1.tgz", + "integrity": "sha512-Y8UyLZvBPgckGhEIFCGBPj1tsRbpcZn4rbAp7lUxC3EW/nDR2V6t9LltE+mvDJxQQ+Bg3saE3UAwn6lsG5O1yQ==", + "dev": true + }, "abab": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", @@ -6098,6 +6104,12 @@ "spdx-expression-parse": "3.0.0" } }, + "validator": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.2.0.tgz", + "integrity": "sha512-gz/uknWtNfZTj1BLUzYHDxOoiQ7A4wZ6xPuuE6RpxswR4cNyT4I5kN9jmU0AQr7IBEap9vfYChI2TpssTN6Itg==", + "dev": true + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", diff --git a/package.json b/package.json index 0cf55d0..3ffd898 100644 --- a/package.json +++ b/package.json @@ -20,14 +20,23 @@ "skipBabel": true } }, - "moduleFileExtensions": ["js", "ts", "json"], + "moduleFileExtensions": [ + "js", + "ts", + "json" + ], "transform": { "^.+\\.(ts|tsx)$": "./node_modules/ts-jest/preprocessor.js" }, - "testMatch": ["**/test/**/*.test.ts", "**/test/**/*.test.js"], + "testMatch": [ + "**/test/**/*.test.ts", + "**/test/**/*.test.js" + ], "testEnvironment": "node" }, - "files": ["dist/**/*"], + "files": [ + "dist/**/*" + ], "main": "./dist/lib/index.js", "types": "./dist/lib/index.d.ts", "repository": { @@ -65,6 +74,7 @@ "@types/mongoose": "^4.7.31", "@types/pluralize": "^0.0.28", "@types/sinon": "^4.1.2", + "@types/validator": "^9.4.1", "collect.js": "^4.0.11", "coveralls": "^3.0.0", "jest": "^21.2.1", @@ -73,6 +83,7 @@ "sinon": "^4.1.3", "ts-jest": "^21.2.3", "tslint": "^5.8.0", - "typescript": "^2.6.2" + "typescript": "^2.6.2", + "validator": "^10.2.0" } } diff --git a/yarn.lock b/yarn.lock index e8ccbaa..a8e9d95 100644 --- a/yarn.lock +++ b/yarn.lock @@ -70,6 +70,10 @@ version "4.1.3" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.1.3.tgz#2ee25e0e302f31e78a945650a60029e08878eaf8" +"@types/validator@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@types/validator/-/validator-9.4.1.tgz#bea5a290e61f1cbf12af3fd878706aeec2ba0087" + abab@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" @@ -132,18 +136,12 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -ansi-styles@^3.1.0: +ansi-styles@^3.1.0, ansi-styles@^3.2.0: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" dependencies: color-convert "^1.9.0" -ansi-styles@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" - dependencies: - color-convert "^1.9.0" - anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" @@ -593,7 +591,7 @@ center-align@^0.1.1: align-text "^0.1.3" lazy-cache "^1.0.3" -chalk@2.3.0: +chalk@2.3.0, chalk@^2.0.1, chalk@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" dependencies: @@ -611,14 +609,6 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.1, chalk@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796" - dependencies: - ansi-styles "^3.2.0" - escape-string-regexp "^1.0.5" - supports-color "^5.2.0" - chance@^1.0.13: version "1.0.13" resolved "https://registry.yarnpkg.com/chance/-/chance-1.0.13.tgz#666bec2db42b3084456a3e4f4c28a82db5ccb7e6" @@ -710,11 +700,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@^2.12.1: - version "2.14.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" - -commander@^2.13.0: +commander@^2.12.1, commander@^2.13.0: version "2.15.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" @@ -2795,10 +2781,6 @@ process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" -process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -2865,7 +2847,7 @@ read-pkg@^2.0.0: normalize-package-data "^2.3.2" path-type "^2.0.0" -readable-stream@2.3.3: +readable-stream@2.3.3, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" dependencies: @@ -2877,18 +2859,6 @@ readable-stream@2.3.3: string_decoder "~1.0.3" util-deprecate "~1.0.1" -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4: - version "2.3.4" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.4.tgz#c946c3f47fa7d8eabc0b6150f4a12f69a4574071" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - readdirp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" @@ -3031,13 +3001,7 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.1.6: - version "1.6.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.6.0.tgz#0fbd21278b27b4004481c395349e7aba60a9ff5c" - dependencies: - path-parse "^1.0.5" - -resolve@^1.1.7, resolve@^1.3.2: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2: version "1.5.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" dependencies: @@ -3384,7 +3348,7 @@ supports-color@^4.0.0: dependencies: has-flag "^2.0.0" -supports-color@^5.1.0, supports-color@^5.2.0: +supports-color@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.2.0.tgz#b0d5333b1184dd3666cbe5aa0b45c5ac7ac17a4a" dependencies: