Test cases for database (#16)
* fix: remove unused import * fix: use env instead of hard code for create database instance * refactor: change most "all" hook to "each" hook * refactor: split test suits into files * add: use DB_LOG_SQL in env to control SQL in log * add: test for logical operator and fixes
This commit is contained in:
parent
53729e188a
commit
b0ba1472bb
@ -5,6 +5,9 @@ DB_DATABASE=nocobase
|
||||
DB_USER=test
|
||||
DB_PASSWORD=test
|
||||
|
||||
# set to 'on' to enable log
|
||||
DB_LOG_SQL=
|
||||
|
||||
# DB_DIALECT=mysql
|
||||
# DB_PORT=3306
|
||||
|
||||
|
@ -2,9 +2,9 @@ import { resolve } from 'path';
|
||||
|
||||
import glob from 'glob';
|
||||
import Koa from 'koa';
|
||||
import { Options, Dialect } from 'sequelize';
|
||||
import { Dialect } from 'sequelize';
|
||||
import bodyParser from 'koa-bodyparser';
|
||||
import supertest, { SuperAgentTest } from 'supertest';
|
||||
import supertest from 'supertest';
|
||||
|
||||
import Database, { requireModule } from '@nocobase/database';
|
||||
import Resourcer from '@nocobase/resourcer';
|
||||
|
@ -3,11 +3,21 @@ import {
|
||||
HasMany, HasOne, Integer, BelongsTo, BelongsToMany
|
||||
} from '../fields';
|
||||
import { DataTypes } from 'sequelize';
|
||||
import Database from '..';
|
||||
|
||||
let db: Database;
|
||||
|
||||
beforeEach(() => {
|
||||
db = getDatabase();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
db.close();
|
||||
});
|
||||
|
||||
describe('associations', () => {
|
||||
describe('hasOne', () => {
|
||||
it('shound be defaults', async () => {
|
||||
const db = getDatabase();
|
||||
it('should be defaults', async () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
});
|
||||
@ -25,8 +35,7 @@ describe('associations', () => {
|
||||
expect(field.options.foreignKey).toBe('bar_id');
|
||||
expect(field.options.sourceKey).toBe('id');
|
||||
});
|
||||
it('shound be ok when the association table is defined later', async () => {
|
||||
const db = getDatabase();
|
||||
it('should be ok when the association table is defined later', async () => {
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
@ -44,8 +53,7 @@ describe('associations', () => {
|
||||
expect(field.options.foreignKey).toBe('bar_id');
|
||||
expect(field.options.sourceKey).toBe('id');
|
||||
});
|
||||
it('shound be custom when target is defined', () => {
|
||||
const db = getDatabase();
|
||||
it('should be custom when target is defined', () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
});
|
||||
@ -65,8 +73,7 @@ describe('associations', () => {
|
||||
expect(field.options.sourceKey).toBe('id');
|
||||
});
|
||||
|
||||
it('shound be custom when sourceKey is defined', () => {
|
||||
const db = getDatabase();
|
||||
it('should be custom when sourceKey is defined', () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
});
|
||||
@ -86,8 +93,7 @@ describe('associations', () => {
|
||||
expect(field.options.sourceKey).toBe('sid');
|
||||
});
|
||||
|
||||
it('shound be integer type when the column of sourceKey does not exist', () => {
|
||||
const db = getDatabase();
|
||||
it('should be integer type when the column of sourceKey does not exist', () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
});
|
||||
@ -112,8 +118,7 @@ describe('associations', () => {
|
||||
});
|
||||
|
||||
describe('hasMany', () => {
|
||||
it('shound be defaults', async () => {
|
||||
const db = getDatabase();
|
||||
it('should be defaults', async () => {
|
||||
db.table({
|
||||
name: 'foo',
|
||||
});
|
||||
@ -131,8 +136,7 @@ describe('associations', () => {
|
||||
expect(field.options.foreignKey).toBe('bar_id');
|
||||
expect(field.options.sourceKey).toBe('id');
|
||||
});
|
||||
it('shound be ok when the association table is defined later', async () => {
|
||||
const db = getDatabase();
|
||||
it('should be ok when the association table is defined later', async () => {
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
@ -150,8 +154,7 @@ describe('associations', () => {
|
||||
expect(field.options.foreignKey).toBe('bar_id');
|
||||
expect(field.options.sourceKey).toBe('id');
|
||||
});
|
||||
it('shound be custom when target is defined', () => {
|
||||
const db = getDatabase();
|
||||
it('should be custom when target is defined', () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
});
|
||||
@ -171,8 +174,7 @@ describe('associations', () => {
|
||||
expect(field.options.sourceKey).toBe('id');
|
||||
});
|
||||
|
||||
it('shound be custom when sourceKey is defined', () => {
|
||||
const db = getDatabase();
|
||||
it('should be custom when sourceKey is defined', () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
});
|
||||
@ -192,8 +194,7 @@ describe('associations', () => {
|
||||
expect(field.options.sourceKey).toBe('sid');
|
||||
});
|
||||
|
||||
it('shound be integer type when the column of sourceKey does not exist', () => {
|
||||
const db = getDatabase();
|
||||
it('should be integer type when the column of sourceKey does not exist', () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
});
|
||||
@ -218,8 +219,7 @@ describe('associations', () => {
|
||||
});
|
||||
|
||||
describe('belongsTo', () => {
|
||||
it('shound be custom foreignKey', async () => {
|
||||
const db = getDatabase();
|
||||
it('should be custom foreignKey', async () => {
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
@ -236,8 +236,7 @@ describe('associations', () => {
|
||||
expect(field.options.targetKey).toBe('id');
|
||||
expect(field.options.foreignKey).toBe('foo_id');
|
||||
});
|
||||
it('shound be custom foreignKey', async () => {
|
||||
const db = getDatabase();
|
||||
it('should be custom foreignKey', async () => {
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
@ -255,8 +254,7 @@ describe('associations', () => {
|
||||
expect(field.options.targetKey).toBe('id');
|
||||
expect(field.options.foreignKey).toBe('custom_foo_id');
|
||||
});
|
||||
it('shound be custom primaryKey', () => {
|
||||
const db = getDatabase();
|
||||
it('should be custom primaryKey', () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
fields: [
|
||||
@ -282,8 +280,7 @@ describe('associations', () => {
|
||||
expect(field.options.targetKey).toBe('fid');
|
||||
expect(field.options.foreignKey).toBe('foo_fid');
|
||||
});
|
||||
it('shound be custom primaryKey', () => {
|
||||
const db = getDatabase();
|
||||
it('should be custom primaryKey', () => {
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
@ -309,8 +306,7 @@ describe('associations', () => {
|
||||
expect(field.options.targetKey).toBe('fid');
|
||||
expect(field.options.foreignKey).toBe('foo_fid');
|
||||
});
|
||||
it('shound throw error', () => {
|
||||
const db = getDatabase();
|
||||
it('should throw error', () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
});
|
||||
@ -327,8 +323,7 @@ describe('associations', () => {
|
||||
});
|
||||
}).toThrow('Unknown attribute "fid" passed as targetKey, define this attribute on model "foos" first')
|
||||
});
|
||||
it('shound be ok when the association table is defined later', async () => {
|
||||
const db = getDatabase();
|
||||
it('should be ok when the association table is defined later', async () => {
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
@ -353,8 +348,7 @@ describe('associations', () => {
|
||||
expect(field.options.foreignKey).toBe('foo_fid');
|
||||
});
|
||||
|
||||
it('shound work', async () => {
|
||||
const db = getDatabase();
|
||||
it('should work', async () => {
|
||||
db.table({
|
||||
name: 'rows',
|
||||
fields: [
|
||||
@ -392,10 +386,7 @@ describe('associations', () => {
|
||||
});
|
||||
|
||||
describe('belongsToMany', () => {
|
||||
it('shound be defaults', async () => {
|
||||
const db = getDatabase({
|
||||
logging: false,
|
||||
});
|
||||
it('should be defaults', async () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
fields: [
|
||||
@ -447,8 +438,7 @@ describe('associations', () => {
|
||||
expect(db.getModel('bars').associations.foos).toBeDefined();
|
||||
});
|
||||
|
||||
it('shound be correct when use custom primary key', async () => {
|
||||
const db = getDatabase();
|
||||
it('should be correct when use custom primary key', async () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
fields: [
|
||||
@ -515,9 +505,6 @@ describe('associations', () => {
|
||||
});
|
||||
|
||||
it('through be defined after source and target', async () => {
|
||||
const db = getDatabase({
|
||||
logging: false,
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
fields: [
|
||||
@ -555,9 +542,6 @@ describe('associations', () => {
|
||||
});
|
||||
|
||||
it('through be defined after source', async () => {
|
||||
const db = getDatabase({
|
||||
logging: false,
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
fields: [
|
||||
@ -596,9 +580,6 @@ describe('associations', () => {
|
||||
});
|
||||
|
||||
it('#', () => {
|
||||
const db = getDatabase({
|
||||
logging: false,
|
||||
});
|
||||
db.table({
|
||||
name: 'posts',
|
||||
fields: [
|
||||
@ -657,8 +638,7 @@ describe('associations', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('shound be defined', () => {
|
||||
const db = getDatabase();
|
||||
it('should be defined', () => {
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
|
@ -1,37 +1,25 @@
|
||||
import Database from '../database';
|
||||
import { Options } from 'sequelize';
|
||||
import { Dialect } from 'sequelize';
|
||||
|
||||
export const config: {
|
||||
[key: string]: Options;
|
||||
} = {
|
||||
mysql: {
|
||||
username: 'test',
|
||||
password: 'test',
|
||||
database: 'test',
|
||||
host: '127.0.0.1',
|
||||
port: 43306,
|
||||
dialect: 'mysql',
|
||||
},
|
||||
postgres: {
|
||||
username: 'test',
|
||||
password: 'test',
|
||||
database: 'test',
|
||||
host: '127.0.0.1',
|
||||
port: 45432,
|
||||
dialect: 'postgres',
|
||||
define: {
|
||||
hooks: {
|
||||
beforeCreate(model, options) {
|
||||
|
||||
},
|
||||
|
||||
|
||||
const config = {
|
||||
username: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_DATABASE,
|
||||
host: process.env.DB_HOST,
|
||||
port: Number.parseInt(process.env.DB_PORT, 10),
|
||||
dialect: process.env.DB_DIALECT as Dialect,
|
||||
define: {
|
||||
hooks: {
|
||||
beforeCreate(model, options) {
|
||||
|
||||
},
|
||||
},
|
||||
// logging: false,
|
||||
},
|
||||
logging: false,
|
||||
};
|
||||
|
||||
export function getDatabase(options: Options = {}) {
|
||||
// console.log(process.env.DB_DIALECT);
|
||||
const db = new Database({...config[process.env.DB_DIALECT||'postgres'], ...options});
|
||||
return db;
|
||||
export function getDatabase() {
|
||||
return new Database(config);
|
||||
};
|
||||
|
@ -1,18 +1,23 @@
|
||||
import { getDatabase } from '.';
|
||||
import Database from '..';
|
||||
import { getDatabase } from '.';
|
||||
import { Op, Sequelize } from 'sequelize';
|
||||
import Model from '../model';
|
||||
import Model, { ModelCtor } from '../model';
|
||||
import { BelongsToMany } from '../fields';
|
||||
import { Mode } from 'fs';
|
||||
|
||||
|
||||
let db: Database;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = await getDatabase();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
describe('actions', () => {
|
||||
let db: Database;
|
||||
|
||||
beforeAll(async () => {
|
||||
db = getDatabase({
|
||||
logging: false,
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
db.table({
|
||||
name: 'users',
|
||||
tableName: 'user1234',
|
||||
@ -196,11 +201,6 @@ describe('actions', () => {
|
||||
await db.sync({
|
||||
force: true,
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('through attributes', async () => {
|
||||
@ -235,9 +235,9 @@ describe('actions', () => {
|
||||
it('scope', async () => {
|
||||
const [User, Post, Comment] = db.getModels(['users', 'posts', 'comments']);
|
||||
const user1 = await User.create();
|
||||
const user2 =await User.create();
|
||||
const user3 =await User.create();
|
||||
const user4 =await User.create();
|
||||
const user2 = await User.create();
|
||||
const user3 = await User.create();
|
||||
const user4 = await User.create();
|
||||
const post = await Post.create();
|
||||
const comment = await Comment.create();
|
||||
comment.updateAssociations({
|
||||
@ -265,16 +265,144 @@ describe('actions', () => {
|
||||
],
|
||||
});
|
||||
const comments = await post.getCurrent_user_comments();
|
||||
// console.log(comments);
|
||||
// TODO: no expect
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseApiJson', () => {
|
||||
let db: Database;
|
||||
let Foo: ModelCtor<Model>;
|
||||
beforeEach(() => {
|
||||
db = getDatabase();
|
||||
db.table({
|
||||
name: 'bazs',
|
||||
tableName: 'bazs_model'
|
||||
});
|
||||
db.table({
|
||||
name: 'bays',
|
||||
tableName: 'bays_model'
|
||||
});
|
||||
db.table({
|
||||
name: 'bars',
|
||||
tableName: 'bars_model',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'baz',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'bay',
|
||||
},
|
||||
],
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
tableName: 'foos_model',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'bars',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'fozs',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'coos',
|
||||
},
|
||||
],
|
||||
});
|
||||
db.table({
|
||||
name: 'fozs',
|
||||
tableName: 'fozs_model',
|
||||
});
|
||||
db.table({
|
||||
name: 'coos',
|
||||
tableName: 'coos_model',
|
||||
});
|
||||
Foo = db.getModel('foos');
|
||||
});
|
||||
|
||||
afterEach(() => db.close());
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
filter: {
|
||||
col1: 'co2',
|
||||
}
|
||||
});
|
||||
expect(data).toEqual({ where: { col1: 'co2' } });
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1'],
|
||||
});
|
||||
expect(data).toEqual({ attributes: ['col1'] });
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1'],
|
||||
filter: {
|
||||
col1: 'co2',
|
||||
},
|
||||
});
|
||||
expect(data).toEqual({ attributes: ['col1'], where: { col1: 'co2' } });
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1'],
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
col1: 'val1',
|
||||
}
|
||||
},
|
||||
});
|
||||
expect(data).toEqual({
|
||||
attributes: ['col1'],
|
||||
where: { col1: 'val1' },
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
where: { col1: 'val1' },
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1', 'bars.col1'],
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
col1: 'val1',
|
||||
}
|
||||
},
|
||||
});
|
||||
expect(data).toEqual({
|
||||
attributes: ['col1'],
|
||||
where: { col1: 'val1' },
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: ['col1'],
|
||||
where: { col1: 'val1' },
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('findByApiJson', () => {
|
||||
it('q', async () => {
|
||||
|
||||
db.getModel('tags').addScope('scopeName', (name, ctx) => {
|
||||
expect(ctx.scopeName).toBe(name);
|
||||
console.log(ctx);
|
||||
return {
|
||||
where: {
|
||||
name: name,
|
||||
@ -330,7 +458,11 @@ describe('actions', () => {
|
||||
scopeName: 'tag3',
|
||||
},
|
||||
});
|
||||
console.log(options);
|
||||
|
||||
try{
|
||||
// DatabaseError [SequelizeDatabaseError]: column tags.scopeName does not exist
|
||||
// SELECT count("posts"."id") AS "count" FROM "post123456" AS "posts" INNER JOIN ( "posts_tags1234" AS "tags->posts_tags" INNER JOIN "tag1234" AS "tags" ON "tags"."id" = "tags->posts_tags"."tag_id") ON "posts"."id" = "tags->posts_tags"."post_id" AND "tags"."scopeName" = 'tag3' INNER JOIN "user1234" AS "user" ON "posts"."user_id" = "user"."id" AND "user"."name" = 'name112233' WHERE "posts"."title" = 'title112233';
|
||||
const { rows, count } = await Post.findAndCountAll({
|
||||
...options,
|
||||
// group: ['id'],
|
||||
@ -340,11 +472,14 @@ describe('actions', () => {
|
||||
|
||||
// console.log(JSON.stringify(rows[0].toJSON(), null, 2));
|
||||
|
||||
rows.forEach(post => {
|
||||
// expect(post.toJSON()).toEqual({ title: 'title112233', 'tags_count': 3, user: { name: 'name112233', posts_count: 1 } });
|
||||
expect(post.get('title')).toBe('title112233');
|
||||
expect(post.user.get('name')).toBe('name112233');
|
||||
rows.forEach(row => {
|
||||
// expect(row.toJSON()).toEqual({ title: 'title112233', 'tags_count': 3, user: { name: 'name112233', posts_count: 1 } });
|
||||
expect(row.get('title')).toBe('title112233');
|
||||
expect(row.user.get('name')).toBe('name112233');
|
||||
});
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
// console.log(count);
|
||||
|
||||
@ -878,15 +1013,11 @@ describe('actions', () => {
|
||||
});
|
||||
|
||||
describe('belongsToMany', () => {
|
||||
let db: Database;
|
||||
let post: Model;
|
||||
let tag1: Model;
|
||||
let tag2: Model;
|
||||
|
||||
beforeAll(async () => {
|
||||
db = getDatabase({
|
||||
logging: false,
|
||||
});
|
||||
beforeEach(async () => {
|
||||
db.table({
|
||||
name: 'posts',
|
||||
tableName: 't333333_posts',
|
||||
@ -928,10 +1059,6 @@ describe('belongsToMany', () => {
|
||||
tag2 = await Tag.create({name: 'tag2'});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('@', async () => {
|
||||
await post.updateAssociations({
|
||||
tags: tag1.name,
|
||||
|
@ -1,21 +1,27 @@
|
||||
import Database from '..';
|
||||
import { getDatabase } from './';
|
||||
|
||||
|
||||
|
||||
let db: Database;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = await getDatabase();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
describe('db sync', () => {
|
||||
describe('table.sync', () => {
|
||||
it('shound be ok1', async () => {
|
||||
const db = getDatabase({
|
||||
logging: false,
|
||||
});
|
||||
const table = db.table({
|
||||
name: 'foos',
|
||||
});
|
||||
await table.sync();
|
||||
await db.close();
|
||||
});
|
||||
it('sync#belongsTo', async () => {
|
||||
const db = getDatabase({
|
||||
logging: false,
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
tableName: 'foos1',
|
||||
@ -43,12 +49,8 @@ describe('db sync', () => {
|
||||
drop: false,
|
||||
}
|
||||
});
|
||||
await db.close();
|
||||
});
|
||||
it('sync#hasMany', async () => {
|
||||
const db = getDatabase({
|
||||
logging: false,
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
tableName: 'foos2',
|
||||
@ -76,12 +78,8 @@ describe('db sync', () => {
|
||||
drop: false,
|
||||
}
|
||||
});
|
||||
await db.close();
|
||||
});
|
||||
it('sync#belongsToMany', async () => {
|
||||
const db = getDatabase({
|
||||
logging: false,
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
fields: [
|
||||
@ -134,12 +132,8 @@ describe('db sync', () => {
|
||||
col1: 'val1'
|
||||
});
|
||||
expect(await db.getModel('bars').count()).toBe(2);
|
||||
await db.close();
|
||||
});
|
||||
it('shound be ok2', async () => {
|
||||
const db = getDatabase({
|
||||
logging: false,
|
||||
});
|
||||
const table = db.table({
|
||||
name: 'goos',
|
||||
});
|
||||
@ -166,7 +160,6 @@ describe('db sync', () => {
|
||||
drop: false,
|
||||
}
|
||||
});
|
||||
await db.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -3,20 +3,19 @@ import Database from '../database';
|
||||
import Table from '../table';
|
||||
import Model from '../model';
|
||||
|
||||
let db: Database;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = await getDatabase();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
describe('tables', () => {
|
||||
let db: Database;
|
||||
|
||||
// beforeAll(() => {
|
||||
// db = getDatabase();
|
||||
// });
|
||||
|
||||
// afterAll(async () => {
|
||||
// await db.sequelize.close();
|
||||
// });
|
||||
|
||||
describe('options', () => {
|
||||
it('shoud be defined', () => {
|
||||
db = getDatabase();
|
||||
it('should be defined', () => {
|
||||
db.table({
|
||||
name: 'foo',
|
||||
});
|
||||
@ -34,7 +33,6 @@ describe('tables', () => {
|
||||
return 'test12345';
|
||||
}
|
||||
}
|
||||
db = getDatabase();
|
||||
const table = db.table({
|
||||
name: 'abc',
|
||||
model: Abc,
|
||||
@ -44,8 +42,7 @@ describe('tables', () => {
|
||||
expect(Abc.getModel('abc').test12345()).toBe('test12345');
|
||||
});
|
||||
|
||||
it('shoud tableName === name', async () => {
|
||||
db = getDatabase();
|
||||
it('should tableName === name', async () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
});
|
||||
@ -53,8 +50,7 @@ describe('tables', () => {
|
||||
expect(db.getModel('foos').getTableName()).toBe('foos');
|
||||
});
|
||||
|
||||
it('shoud be custom when tableName is defined', async () => {
|
||||
db = getDatabase();
|
||||
it('should be custom when tableName is defined', async () => {
|
||||
db.table({
|
||||
name: 'bar',
|
||||
tableName: 'bar_v2'
|
||||
@ -63,8 +59,7 @@ describe('tables', () => {
|
||||
expect(db.getModel('bar').getTableName()).toBe('bar_v2');
|
||||
});
|
||||
|
||||
it('shoud be custom when timestamps is defined', async () => {
|
||||
db = getDatabase();
|
||||
it('should be custom when timestamps is defined', async () => {
|
||||
db.table({
|
||||
name: 'baz',
|
||||
createdAt: 'created',
|
||||
@ -74,8 +69,7 @@ describe('tables', () => {
|
||||
expect(db.getModel('baz').rawAttributes.updated).toBeDefined();
|
||||
});
|
||||
|
||||
it('index shound be defined', async () => {
|
||||
db = getDatabase();
|
||||
it('index should be defined', async () => {
|
||||
db.table({
|
||||
name: 'baz',
|
||||
fields: [
|
||||
@ -104,8 +98,7 @@ describe('tables', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('index shound be defined', async () => {
|
||||
db = getDatabase();
|
||||
it('index should be defined', async () => {
|
||||
db.table({
|
||||
name: 'baz2',
|
||||
indexes: [
|
||||
@ -140,8 +133,7 @@ describe('tables', () => {
|
||||
});
|
||||
|
||||
describe('#extend()', () => {
|
||||
it('shoud be extend', async () => {
|
||||
db = getDatabase();
|
||||
it('should be extend', async () => {
|
||||
db.table({
|
||||
name: 'baz',
|
||||
});
|
||||
@ -155,8 +147,7 @@ describe('tables', () => {
|
||||
expect(db.getModel('baz').rawAttributes.created).toBeDefined();
|
||||
expect(db.getModel('baz').rawAttributes.updated).toBeDefined();
|
||||
});
|
||||
it('shoud be extend', async () => {
|
||||
db = getDatabase();
|
||||
it('should be extend', async () => {
|
||||
db.table({
|
||||
name: 'foos',
|
||||
});
|
||||
@ -196,10 +187,9 @@ describe('tables', () => {
|
||||
|
||||
describe('associations', () => {
|
||||
beforeAll(() => {
|
||||
db = getDatabase();
|
||||
});
|
||||
|
||||
it('shound be undefined when target table does not exist', () => {
|
||||
it('should be undefined when target table does not exist', () => {
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
@ -212,14 +202,22 @@ describe('tables', () => {
|
||||
expect(db.getModel('bars').associations.foo).toBeUndefined();
|
||||
});
|
||||
|
||||
it('shound be defined when target table exists', () => {
|
||||
it('should be defined when target table exists', () => {
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasOne',
|
||||
name: 'foo',
|
||||
}
|
||||
],
|
||||
});
|
||||
db.table({name: 'foos'});
|
||||
expect(db.getModel('bars').associations.foo).toBeDefined();
|
||||
});
|
||||
|
||||
describe('#setFields()', () => {
|
||||
beforeAll(() => {
|
||||
db = getDatabase();
|
||||
beforeEach(() => {
|
||||
db.table({
|
||||
name: 'table1',
|
||||
fields: [
|
||||
@ -239,13 +237,13 @@ describe('tables', () => {
|
||||
name: 'table2',
|
||||
});
|
||||
});
|
||||
it('shound be defined', () => {
|
||||
it('should be defined', () => {
|
||||
const table1 = db.getModel('table1');
|
||||
expect(Object.keys(table1.associations).length).toBe(2);
|
||||
expect(table1.associations.table21).toBeDefined();
|
||||
expect(table1.associations.table22).toBeDefined();
|
||||
});
|
||||
it('shound be defined', () => {
|
||||
it('should be defined', () => {
|
||||
db.getTable('table1').setFields([
|
||||
{
|
||||
type: 'string',
|
||||
@ -267,8 +265,7 @@ describe('tables', () => {
|
||||
});
|
||||
|
||||
describe('#addField()', () => {
|
||||
beforeAll(() => {
|
||||
db = getDatabase();
|
||||
beforeEach(() => {
|
||||
db.table({
|
||||
name: 'table1',
|
||||
});
|
||||
@ -276,7 +273,7 @@ describe('tables', () => {
|
||||
name: 'table2',
|
||||
});
|
||||
});
|
||||
it('shound be defined when the field be added after initialization', () => {
|
||||
it('should be defined when the field be added after initialization', () => {
|
||||
db.getTable('table1').addField({
|
||||
type: 'hasOne',
|
||||
name: 'table2',
|
||||
@ -285,7 +282,12 @@ describe('tables', () => {
|
||||
expect(Object.keys(db.getModel('table1').associations).length).toBe(1);
|
||||
expect(db.getModel('table1').associations.table2).toBeDefined();
|
||||
});
|
||||
it('shound be defined when continue to add', () => {
|
||||
it('should be defined when continue to add', () => {
|
||||
db.getTable('table1').addField({
|
||||
type: 'hasOne',
|
||||
name: 'table2',
|
||||
target: 'table2',
|
||||
});
|
||||
db.getTable('table1').addField({
|
||||
type: 'hasOne',
|
||||
name: 'table21',
|
||||
|
@ -28,7 +28,7 @@ import Database from '..';
|
||||
|
||||
describe('field types', () => {
|
||||
const assertTypeInstanceOf = (expected, actual) => {
|
||||
const db = getDatabase();
|
||||
const db: Database = getDatabase();
|
||||
const table = db.table({
|
||||
name: 'test',
|
||||
});
|
||||
@ -56,6 +56,7 @@ describe('field types', () => {
|
||||
expect(type).toBe(field.getDataType());
|
||||
}
|
||||
}
|
||||
db.close();
|
||||
}
|
||||
|
||||
it('shound be boolean', () => {
|
||||
@ -212,7 +213,7 @@ describe('field types', () => {
|
||||
|
||||
describe('virtual', () => {
|
||||
let db: Database;
|
||||
beforeAll(async () => {
|
||||
beforeEach(async () => {
|
||||
db = getDatabase();
|
||||
db.table({
|
||||
name: 'formula_tests',
|
||||
@ -283,7 +284,7 @@ describe('field types', () => {
|
||||
})
|
||||
await db.sync({force: true});
|
||||
});
|
||||
afterAll(async () => {
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
});
|
||||
it('pwd', async () => {
|
||||
|
@ -1,658 +0,0 @@
|
||||
import { requireModule, toWhere, toInclude } from '../utils';
|
||||
import path from 'path';
|
||||
import { Op } from 'sequelize';
|
||||
import { getDatabase } from '.';
|
||||
import Database from '../database';
|
||||
import Model, { ModelCtor } from '../model';
|
||||
|
||||
describe('utils', () => {
|
||||
describe('toWhere', () => {
|
||||
it('Op.eq', () => {
|
||||
const where = toWhere({
|
||||
id: {
|
||||
eq: 12
|
||||
},
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: {
|
||||
[Op.eq]: 12,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.ilike', () => {
|
||||
const where = toWhere({
|
||||
id: {
|
||||
ilike: 'val1'
|
||||
},
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: {
|
||||
[Op.iLike]: 'val1',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.ilike', () => {
|
||||
const where = toWhere({
|
||||
'id.ilike': 'val1',
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: {
|
||||
[Op.iLike]: 'val1',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.is null', () => {
|
||||
const where = toWhere({
|
||||
'id.is': null,
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: {
|
||||
[Op.is]: null,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.in', () => {
|
||||
const where = toWhere({
|
||||
id: {
|
||||
in: [12]
|
||||
},
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: {
|
||||
[Op.in]: [12],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.in', () => {
|
||||
const where = toWhere({
|
||||
'id.in': [11, 12],
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: {
|
||||
[Op.in]: [11, 12],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('association', () => {
|
||||
let db: Database;
|
||||
let Foo: ModelCtor<Model>;
|
||||
beforeAll(() => {
|
||||
db = getDatabase();
|
||||
db.table({
|
||||
name: 'bazs',
|
||||
});
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'baz',
|
||||
}
|
||||
]
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'bars',
|
||||
}
|
||||
],
|
||||
});
|
||||
Foo = db.getModel('foos');
|
||||
});
|
||||
|
||||
const toWhereExpect = (options, logging = false) => {
|
||||
const where = toWhere(options, {
|
||||
associations: Foo.associations,
|
||||
});
|
||||
return expect(where);
|
||||
}
|
||||
|
||||
it('association', () => {
|
||||
toWhereExpect({
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
name: {
|
||||
ilike: 'aa',
|
||||
},
|
||||
col2: {
|
||||
lt: 2,
|
||||
},
|
||||
baz: {
|
||||
col1: 12,
|
||||
},
|
||||
},
|
||||
'bars.col3.ilike': 'aa',
|
||||
}).toEqual({
|
||||
col1: 'val1',
|
||||
$__include: {
|
||||
bars: {
|
||||
name: {
|
||||
[Op.iLike]: 'aa',
|
||||
},
|
||||
col2: {
|
||||
[Op.lt]: 2,
|
||||
},
|
||||
col3: {
|
||||
[Op.iLike]: 'aa',
|
||||
},
|
||||
$__include: {
|
||||
baz: {
|
||||
col1: 12
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toInclude', () => {
|
||||
let db: Database;
|
||||
let Foo: ModelCtor<Model>;
|
||||
beforeAll(() => {
|
||||
db = getDatabase();
|
||||
db.table({
|
||||
name: 'bazs',
|
||||
});
|
||||
db.table({
|
||||
name: 'bays',
|
||||
});
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'baz',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'bay',
|
||||
},
|
||||
],
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'bars',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'fozs',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'coos',
|
||||
},
|
||||
],
|
||||
});
|
||||
db.table({
|
||||
name: 'fozs',
|
||||
});
|
||||
db.table({
|
||||
name: 'coos',
|
||||
});
|
||||
Foo = db.getModel('foos');
|
||||
});
|
||||
|
||||
const toIncludeExpect = (options: any, logging = false) => {
|
||||
const include = toInclude(options, {
|
||||
Model: Foo,
|
||||
associations: Foo.associations,
|
||||
});
|
||||
if (logging) {
|
||||
console.log(JSON.stringify(include, null, 2));
|
||||
}
|
||||
return expect(include);
|
||||
};
|
||||
|
||||
it('normal columns', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'col2'],
|
||||
}).toEqual({ attributes: [ 'col1', 'col2' ] });
|
||||
});
|
||||
|
||||
it('association count attribute', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars_count'],
|
||||
}).toEqual({ attributes: [ 'col1', Foo.withCountAttribute('bars') ] });
|
||||
});
|
||||
|
||||
it('association without attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars'],
|
||||
}).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('association attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars.col1', 'bars.col2'],
|
||||
}).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: [ 'col1', 'col2' ],
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('association attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', ['bars', 'col1'], ['bars', 'col2']],
|
||||
}).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: [ 'col1', 'col2' ],
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('nested association', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars.baz'],
|
||||
}).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: [],
|
||||
include: [
|
||||
{
|
||||
association: 'baz',
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('nested association', () => {
|
||||
// TODO,输出 bars 的所有字段
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars', 'bars.baz'],
|
||||
}, true).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
include: [
|
||||
{
|
||||
association: 'baz',
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('nested association', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars.col1', 'bars.col2', 'bars.baz'],
|
||||
}).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: ['col1', 'col2'],
|
||||
include: [
|
||||
{
|
||||
association: 'baz',
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('nested association', () => {
|
||||
// TODO,输出 bars 的所有字段
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars.col1', 'bars.col2', 'bars.baz.col1', 'bars.baz.col2'],
|
||||
}).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: ['col1', 'col2'],
|
||||
include: [
|
||||
{
|
||||
association: 'baz',
|
||||
attributes: ['col1', 'col2'],
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('append attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
appends: ['bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [Foo.withCountAttribute('bars')],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('append attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
appends: ['bars.col1', 'bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [Foo.withCountAttribute('bars')],
|
||||
},
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: {
|
||||
include: ['col1'],
|
||||
},
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('only & append attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
only: ['col1'],
|
||||
appends: ['bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: ['col1', Foo.withCountAttribute('bars')],
|
||||
});
|
||||
});
|
||||
|
||||
it('only & append attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
only: ['col1', 'bars.col1'],
|
||||
appends: ['bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: ['col1', Foo.withCountAttribute('bars')],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: ['col1'],
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('excpet attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
except: ['col1'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [],
|
||||
exclude: ['col1'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('excpet attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
except: ['col1', 'bars.col1'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [],
|
||||
exclude: ['col1'],
|
||||
},
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: {
|
||||
include: [],
|
||||
exclude: ['col1'],
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('excpet & append attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
except: ['col1'],
|
||||
appends: ['bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [Foo.withCountAttribute('bars')],
|
||||
exclude: ['col1'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('where options', () => {
|
||||
it('where', () => {
|
||||
toIncludeExpect({
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
},
|
||||
fields: {
|
||||
except: ['col1'],
|
||||
appends: ['bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [Foo.withCountAttribute('bars')],
|
||||
exclude: ['col1'],
|
||||
},
|
||||
where: {
|
||||
col1: 'val1',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('where', () => {
|
||||
toIncludeExpect({
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
col1: 'val1',
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
except: ['col1'],
|
||||
appends: ['bars', 'bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [Foo.withCountAttribute('bars')],
|
||||
exclude: ['col1'],
|
||||
},
|
||||
where: {
|
||||
col1: 'val1',
|
||||
},
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
where: {
|
||||
col1: 'val1',
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('where', () => {
|
||||
toIncludeExpect({
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
col1: 'val1',
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
except: ['col1'],
|
||||
appends: ['bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [Foo.withCountAttribute('bars')],
|
||||
exclude: ['col1'],
|
||||
},
|
||||
where: {
|
||||
col1: 'val1',
|
||||
},
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
where: {
|
||||
col1: 'val1',
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
filter: {
|
||||
col1: 'co2',
|
||||
}
|
||||
});
|
||||
expect(data).toEqual({ where: { col1: 'co2' } });
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1'],
|
||||
});
|
||||
expect(data).toEqual({ attributes: ['col1'] });
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1'],
|
||||
filter: {
|
||||
col1: 'co2',
|
||||
},
|
||||
});
|
||||
expect(data).toEqual({ attributes: ['col1'], where: { col1: 'co2' } });
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1'],
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
col1: 'val1',
|
||||
}
|
||||
},
|
||||
});
|
||||
expect(data).toEqual({
|
||||
attributes: ['col1'],
|
||||
where: { col1: 'val1' },
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
where: { col1: 'val1' },
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('parseApiJson', () => {
|
||||
const data = Foo.parseApiJson({
|
||||
fields: ['col1', 'bars.col1'],
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
col1: 'val1',
|
||||
}
|
||||
},
|
||||
});
|
||||
expect(data).toEqual({
|
||||
attributes: ['col1'],
|
||||
where: { col1: 'val1' },
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: ['col1'],
|
||||
where: { col1: 'val1' },
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('requireModule', () => {
|
||||
test('toBeTruthy', () => {
|
||||
const r = requireModule(true);
|
||||
expect(r).toBeTruthy();
|
||||
});
|
||||
|
||||
test('toBeInstanceOf Function', () => {
|
||||
const r = requireModule(() => {});
|
||||
expect(r).toBeInstanceOf(Function);
|
||||
});
|
||||
|
||||
test('toBeInstanceOf Function', () => {
|
||||
const r = requireModule(path.resolve(__dirname, './modules/fn'));
|
||||
expect(r).toBeInstanceOf(Function);
|
||||
});
|
||||
|
||||
test('toBeInstanceOf Function', () => {
|
||||
const r = requireModule(path.resolve(__dirname, './modules/fnts'));
|
||||
expect(r).toBeInstanceOf(Function);
|
||||
});
|
||||
|
||||
test('object', () => {
|
||||
const r = requireModule(path.resolve(__dirname, './modules/obj'));
|
||||
expect(r).toEqual({
|
||||
'foo': 'bar',
|
||||
});
|
||||
});
|
||||
|
||||
test('object', () => {
|
||||
const r = requireModule(path.resolve(__dirname, './modules/objts'));
|
||||
expect(r).toEqual({
|
||||
'foo': 'bar',
|
||||
});
|
||||
});
|
||||
|
||||
test('json', () => {
|
||||
const r = requireModule(path.resolve(__dirname, './modules/json'));
|
||||
expect(r).toEqual({
|
||||
'foo': 'bar',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
48
packages/database/src/__tests__/utils/requireModule.test.ts
Normal file
48
packages/database/src/__tests__/utils/requireModule.test.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import path from "path";
|
||||
|
||||
import { requireModule } from "../../utils";
|
||||
|
||||
|
||||
|
||||
describe('utils.requireModule', () => {
|
||||
test('toBeTruthy', () => {
|
||||
const r = requireModule(true);
|
||||
expect(r).toBeTruthy();
|
||||
});
|
||||
|
||||
test('toBeInstanceOf Function', () => {
|
||||
const r = requireModule(() => {});
|
||||
expect(r).toBeInstanceOf(Function);
|
||||
});
|
||||
|
||||
test('toBeInstanceOf Function', () => {
|
||||
const r = requireModule(path.resolve(__dirname, './modules/fn'));
|
||||
expect(r).toBeInstanceOf(Function);
|
||||
});
|
||||
|
||||
test('toBeInstanceOf Function', () => {
|
||||
const r = requireModule(path.resolve(__dirname, './modules/fnts'));
|
||||
expect(r).toBeInstanceOf(Function);
|
||||
});
|
||||
|
||||
test('object', () => {
|
||||
const r = requireModule(path.resolve(__dirname, './modules/obj'));
|
||||
expect(r).toEqual({
|
||||
'foo': 'bar',
|
||||
});
|
||||
});
|
||||
|
||||
test('object', () => {
|
||||
const r = requireModule(path.resolve(__dirname, './modules/objts'));
|
||||
expect(r).toEqual({
|
||||
'foo': 'bar',
|
||||
});
|
||||
});
|
||||
|
||||
test('json', () => {
|
||||
const r = requireModule(path.resolve(__dirname, './modules/json'));
|
||||
expect(r).toEqual({
|
||||
'foo': 'bar',
|
||||
});
|
||||
});
|
||||
});
|
396
packages/database/src/__tests__/utils/toInclude.test.ts
Normal file
396
packages/database/src/__tests__/utils/toInclude.test.ts
Normal file
@ -0,0 +1,396 @@
|
||||
import { getDatabase } from '..';
|
||||
import Database from '../../database';
|
||||
import Model, { ModelCtor } from '../../model';
|
||||
import { toInclude } from '../../utils';
|
||||
|
||||
|
||||
|
||||
describe('toInclude', () => {
|
||||
let db: Database;
|
||||
let Foo: ModelCtor<Model>;
|
||||
beforeEach(() => {
|
||||
db = getDatabase();
|
||||
db.table({
|
||||
name: 'bazs',
|
||||
});
|
||||
db.table({
|
||||
name: 'bays',
|
||||
});
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'baz',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'bay',
|
||||
},
|
||||
],
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'bars',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'fozs',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'coos',
|
||||
},
|
||||
],
|
||||
});
|
||||
db.table({
|
||||
name: 'fozs',
|
||||
});
|
||||
db.table({
|
||||
name: 'coos',
|
||||
});
|
||||
Foo = db.getModel('foos');
|
||||
});
|
||||
|
||||
afterEach(() => db.close());
|
||||
|
||||
const toIncludeExpect = (options: any, logging = false) => {
|
||||
const include = toInclude(options, {
|
||||
Model: Foo,
|
||||
associations: Foo.associations,
|
||||
});
|
||||
if (logging) {
|
||||
console.log(JSON.stringify(include, null, 2));
|
||||
}
|
||||
return expect(include);
|
||||
};
|
||||
|
||||
it('normal columns', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'col2'],
|
||||
}).toEqual({ attributes: [ 'col1', 'col2' ] });
|
||||
});
|
||||
|
||||
it('association count attribute', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars_count'],
|
||||
}).toEqual({ attributes: [ 'col1', Foo.withCountAttribute('bars') ] });
|
||||
});
|
||||
|
||||
it('association without attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars'],
|
||||
}).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('association attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars.col1', 'bars.col2'],
|
||||
}).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: [ 'col1', 'col2' ],
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('association attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', ['bars', 'col1'], ['bars', 'col2']],
|
||||
}).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: [ 'col1', 'col2' ],
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('nested association', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars.baz'],
|
||||
}).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: [],
|
||||
include: [
|
||||
{
|
||||
association: 'baz',
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('nested association', () => {
|
||||
// TODO,输出 bars 的所有字段
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars', 'bars.baz'],
|
||||
}, true).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
include: [
|
||||
{
|
||||
association: 'baz',
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('nested association', () => {
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars.col1', 'bars.col2', 'bars.baz'],
|
||||
}).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: ['col1', 'col2'],
|
||||
include: [
|
||||
{
|
||||
association: 'baz',
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('nested association', () => {
|
||||
// TODO,输出 bars 的所有字段
|
||||
toIncludeExpect({
|
||||
fields: ['col1', 'bars.col1', 'bars.col2', 'bars.baz.col1', 'bars.baz.col2'],
|
||||
}).toEqual({
|
||||
attributes: [ 'col1' ],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: ['col1', 'col2'],
|
||||
include: [
|
||||
{
|
||||
association: 'baz',
|
||||
attributes: ['col1', 'col2'],
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('append attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
appends: ['bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [Foo.withCountAttribute('bars')],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('append attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
appends: ['bars.col1', 'bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [Foo.withCountAttribute('bars')],
|
||||
},
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: {
|
||||
include: ['col1'],
|
||||
},
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('only & append attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
only: ['col1'],
|
||||
appends: ['bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: ['col1', Foo.withCountAttribute('bars')],
|
||||
});
|
||||
});
|
||||
|
||||
it('only & append attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
only: ['col1', 'bars.col1'],
|
||||
appends: ['bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: ['col1', Foo.withCountAttribute('bars')],
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: ['col1'],
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('excpet attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
except: ['col1'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [],
|
||||
exclude: ['col1'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('excpet attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
except: ['col1', 'bars.col1'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [],
|
||||
exclude: ['col1'],
|
||||
},
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
attributes: {
|
||||
include: [],
|
||||
exclude: ['col1'],
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('excpet & append attributes', () => {
|
||||
toIncludeExpect({
|
||||
fields: {
|
||||
except: ['col1'],
|
||||
appends: ['bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [Foo.withCountAttribute('bars')],
|
||||
exclude: ['col1'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('where options', () => {
|
||||
it('where', () => {
|
||||
toIncludeExpect({
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
},
|
||||
fields: {
|
||||
except: ['col1'],
|
||||
appends: ['bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [Foo.withCountAttribute('bars')],
|
||||
exclude: ['col1'],
|
||||
},
|
||||
where: {
|
||||
col1: 'val1',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('where', () => {
|
||||
toIncludeExpect({
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
col1: 'val1',
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
except: ['col1'],
|
||||
appends: ['bars', 'bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [Foo.withCountAttribute('bars')],
|
||||
exclude: ['col1'],
|
||||
},
|
||||
where: {
|
||||
col1: 'val1',
|
||||
},
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
where: {
|
||||
col1: 'val1',
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('where', () => {
|
||||
toIncludeExpect({
|
||||
filter: {
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
col1: 'val1',
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
except: ['col1'],
|
||||
appends: ['bars_count'],
|
||||
},
|
||||
}).toEqual({
|
||||
attributes: {
|
||||
include: [Foo.withCountAttribute('bars')],
|
||||
exclude: ['col1'],
|
||||
},
|
||||
where: {
|
||||
col1: 'val1',
|
||||
},
|
||||
include: [
|
||||
{
|
||||
association: 'bars',
|
||||
where: {
|
||||
col1: 'val1',
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
262
packages/database/src/__tests__/utils/toWhere.test.ts
Normal file
262
packages/database/src/__tests__/utils/toWhere.test.ts
Normal file
@ -0,0 +1,262 @@
|
||||
import { Op } from "sequelize";
|
||||
import Database from "../../database";
|
||||
import Model, { ModelCtor } from '../../model';
|
||||
import { toWhere } from "../../utils";
|
||||
import { getDatabase } from "..";
|
||||
|
||||
describe('utils.toWhere', () => {
|
||||
describe('single', () => {
|
||||
it('=', () => {
|
||||
const where = toWhere({
|
||||
id: 12,
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: 12,
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.eq', () => {
|
||||
const where = toWhere({
|
||||
id: {
|
||||
eq: 12
|
||||
},
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: {
|
||||
[Op.eq]: 12,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.ilike', () => {
|
||||
const where = toWhere({
|
||||
id: {
|
||||
ilike: 'val1'
|
||||
},
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: {
|
||||
[Op.iLike]: 'val1',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.ilike', () => {
|
||||
const where = toWhere({
|
||||
'id.ilike': 'val1',
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: {
|
||||
[Op.iLike]: 'val1',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.is null', () => {
|
||||
const where = toWhere({
|
||||
'id.is': null,
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: {
|
||||
[Op.is]: null,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.in', () => {
|
||||
const where = toWhere({
|
||||
id: {
|
||||
in: [12]
|
||||
},
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: {
|
||||
[Op.in]: [12],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.in', () => {
|
||||
const where = toWhere({
|
||||
'id.in': [11, 12],
|
||||
});
|
||||
expect(where).toEqual({
|
||||
id: {
|
||||
[Op.in]: [11, 12],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Op.between', () => {
|
||||
expect(toWhere({
|
||||
'id.between': [1, 2]
|
||||
})).toEqual({
|
||||
id: { [Op.between]: [1, 2] }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('group by logical operator', () => {
|
||||
it('field.or', () => {
|
||||
expect(toWhere({
|
||||
'id.or': [1, 2]
|
||||
})).toEqual({
|
||||
id: { [Op.or]: [1, 2] }
|
||||
});
|
||||
});
|
||||
|
||||
it('field.and', () => {
|
||||
expect(toWhere({
|
||||
'id.and': [1, 2]
|
||||
})).toEqual({
|
||||
id: { [Op.and]: [1, 2] }
|
||||
});
|
||||
});
|
||||
|
||||
it('root or', () => {
|
||||
expect(toWhere({
|
||||
or: [{ a: 1 }, { b: 2 }]
|
||||
})).toEqual({
|
||||
[Op.or]: [{ a: 1 }, { b: 2 }]
|
||||
});
|
||||
});
|
||||
|
||||
it('root and', () => {
|
||||
expect(toWhere({
|
||||
and: [{ a: 1 }, { b: 2 }]
|
||||
})).toEqual({
|
||||
[Op.and]: [{ a: 1 }, { b: 2 }]
|
||||
});
|
||||
});
|
||||
|
||||
it('root "and" and "or"', () => {
|
||||
expect(toWhere({
|
||||
and: [{ a: 1 }, { b: 2 }],
|
||||
or: [{ c: 3 }, { d: 4 }]
|
||||
})).toEqual({
|
||||
[Op.and]: [{ a: 1 }, { b: 2 }],
|
||||
[Op.or]: [{ c: 3 }, { d: 4 }]
|
||||
});
|
||||
});
|
||||
|
||||
it('root "and" and field', () => {
|
||||
expect(toWhere({
|
||||
and: [{ a: 1 }, { b: 2 }],
|
||||
'id.or': [3, 4]
|
||||
})).toEqual({
|
||||
[Op.and]: [{ a: 1 }, { b: 2 }],
|
||||
id: { [Op.or]: [3, 4] }
|
||||
});
|
||||
});
|
||||
|
||||
it('or in and', () => {
|
||||
expect(toWhere({
|
||||
and: [{ a: 1 }, { 'b.or': [3, 4] }],
|
||||
})).toEqual({
|
||||
[Op.and]: [{ a: 1 }, { b: { [Op.or]: [3, 4] } }],
|
||||
});
|
||||
});
|
||||
|
||||
it('and in or', () => {
|
||||
expect(toWhere({
|
||||
or: [{ a: 1 }, { and: [{ c: 3 }, { d: 4 }] }],
|
||||
})).toEqual({
|
||||
[Op.or]: [{ a: 1 }, { [Op.and]: [{ c: 3 }, { d: 4 }] }],
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: bug
|
||||
it.skip('field as or', () => {
|
||||
expect(toWhere({
|
||||
or: 1,
|
||||
})).toEqual({
|
||||
or: 1,
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: bug
|
||||
it.skip('or for field as or', () => {
|
||||
expect(toWhere({
|
||||
'or.or': [1, 2],
|
||||
})).toEqual({
|
||||
or: { [Op.or]: [1, 2] },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('association', () => {
|
||||
let db: Database;
|
||||
let Foo: ModelCtor<Model>;
|
||||
beforeAll(() => {
|
||||
db = getDatabase();
|
||||
db.table({
|
||||
name: 'bazs',
|
||||
});
|
||||
db.table({
|
||||
name: 'bars',
|
||||
fields: [
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'baz',
|
||||
}
|
||||
]
|
||||
});
|
||||
db.table({
|
||||
name: 'foos',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'bars',
|
||||
}
|
||||
],
|
||||
});
|
||||
Foo = db.getModel('foos');
|
||||
});
|
||||
afterAll(() => db.close());
|
||||
|
||||
const toWhereExpect = (options, logging = false) => {
|
||||
const where = toWhere(options, {
|
||||
associations: Foo.associations,
|
||||
});
|
||||
return expect(where);
|
||||
}
|
||||
|
||||
it('association', () => {
|
||||
toWhereExpect({
|
||||
col1: 'val1',
|
||||
bars: {
|
||||
name: {
|
||||
ilike: 'aa',
|
||||
},
|
||||
col2: {
|
||||
lt: 2,
|
||||
},
|
||||
baz: {
|
||||
col1: 12,
|
||||
},
|
||||
},
|
||||
'bars.col3.ilike': 'aa',
|
||||
}).toEqual({
|
||||
col1: 'val1',
|
||||
$__include: {
|
||||
bars: {
|
||||
name: {
|
||||
[Op.iLike]: 'aa',
|
||||
},
|
||||
col2: {
|
||||
[Op.lt]: 2,
|
||||
},
|
||||
col3: {
|
||||
[Op.iLike]: 'aa',
|
||||
},
|
||||
$__include: {
|
||||
baz: {
|
||||
col1: 12
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -19,9 +19,12 @@ interface ToWhereContext {
|
||||
}
|
||||
|
||||
export function toWhere(options: any, context: ToWhereContext = {}) {
|
||||
if (options === null || Array.isArray(options) || typeof options !== 'object') {
|
||||
if (options === null || typeof options !== 'object') {
|
||||
return options;
|
||||
}
|
||||
if (Array.isArray(options)) {
|
||||
return options.map((item) => toWhere(item, context));
|
||||
}
|
||||
const { Model, associations = {}, ctx, dialect } = context;
|
||||
const items = {};
|
||||
// 先处理「点号」的问题
|
||||
@ -48,6 +51,7 @@ export function toWhere(options: any, context: ToWhereContext = {}) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO: to fix same op key as field name
|
||||
values[op.has(key) ? op.get(key) : key] = toWhere(items[key], context);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user