mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-12-01 03:38:32 +08:00
refactor: mockDatabase
This commit is contained in:
parent
0d0acba357
commit
c5f639338f
@ -1,6 +1,6 @@
|
||||
import { Collection } from '../collection';
|
||||
import { Database } from '../database';
|
||||
import { generatePrefixByPath, mockDatabase } from './index';
|
||||
import { mockDatabase } from './index';
|
||||
|
||||
test('collection disable authGenId', async () => {
|
||||
const db = mockDatabase();
|
||||
@ -91,7 +91,7 @@ describe('collection sync', () => {
|
||||
]);
|
||||
|
||||
await collection.sync();
|
||||
const tableFields = await (<any>collection.model).queryInterface.describeTable(`${generatePrefixByPath()}_users`);
|
||||
const tableFields = await (<any>collection.model).queryInterface.describeTable(`${db.getTablePrefix()}users`);
|
||||
|
||||
expect(tableFields).toHaveProperty('firstName');
|
||||
expect(tableFields).toHaveProperty('lastName');
|
||||
@ -114,7 +114,7 @@ describe('collection sync', () => {
|
||||
|
||||
const model = collection.model;
|
||||
|
||||
const tableFields = await (<any>model).queryInterface.describeTable(`${generatePrefixByPath()}_posts`);
|
||||
const tableFields = await (<any>model).queryInterface.describeTable(`${db.getTablePrefix()}posts`);
|
||||
|
||||
expect(tableFields['user_id']).toBeUndefined();
|
||||
});
|
||||
@ -143,7 +143,7 @@ describe('collection sync', () => {
|
||||
|
||||
const model = collection.model;
|
||||
await collection.sync();
|
||||
const tableFields = await (<any>model).queryInterface.describeTable(`${generatePrefixByPath()}_posts_tags`);
|
||||
const tableFields = await (<any>model).queryInterface.describeTable(`${db.getTablePrefix()}posts_tags`);
|
||||
expect(tableFields['postId']).toBeDefined();
|
||||
expect(tableFields['tagId']).toBeDefined();
|
||||
});
|
||||
@ -184,13 +184,13 @@ test.skip('update collection options', async () => {
|
||||
},
|
||||
);
|
||||
|
||||
expect(collection.model.getTableName()).toEqual(`${generatePrefixByPath()}_posts`);
|
||||
expect(collection.model.getTableName()).toEqual(`${db.getTablePrefix()}posts`);
|
||||
|
||||
collection.updateOptions({
|
||||
name: 'articles',
|
||||
});
|
||||
|
||||
expect(collection.model.getTableName()).toEqual(`${generatePrefixByPath()}_articles`);
|
||||
expect(collection.model.getTableName()).toEqual(`${db.getTablePrefix()}articles`);
|
||||
});
|
||||
|
||||
test('collection with association', async () => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { mockDatabase } from './index';
|
||||
import FilterParser from '../filter-parser';
|
||||
import { Op } from 'sequelize';
|
||||
import { Database } from '../database';
|
||||
import FilterParser from '../filter-parser';
|
||||
import { mockDatabase } from './index';
|
||||
|
||||
test('filter item by string', async () => {
|
||||
const database = mockDatabase();
|
||||
|
@ -1,94 +1 @@
|
||||
import { uid } from '@nocobase/utils';
|
||||
import merge from 'deepmerge';
|
||||
import { Sequelize } from 'sequelize';
|
||||
import { Database, DatabaseOptions } from '../database';
|
||||
|
||||
export function generatePrefixByPath() {
|
||||
const { id } = require.main;
|
||||
const key = id
|
||||
.replace(`${process.env.PWD}/packages`, '')
|
||||
.replace(/src\/__tests__/g, '')
|
||||
.replace('.test.ts', '')
|
||||
.replace(/[^\w]/g, '_')
|
||||
.replace(/_+/g, '_');
|
||||
return key;
|
||||
}
|
||||
|
||||
export function getConfig(config: any = {}, options?: any): DatabaseOptions {
|
||||
if (process.env.DB_DIALECT === 'sqlite') {
|
||||
const defaults = {
|
||||
dialect: process.env.DB_DIALECT as any,
|
||||
storage: ':memory:',
|
||||
logging: process.env.DB_LOG_SQL === 'on' ? console.log : false,
|
||||
// sync: {
|
||||
// force: true,
|
||||
// },
|
||||
hooks: {
|
||||
beforeDefine(model, options) {
|
||||
options.tableName = `${generatePrefixByPath()}_${
|
||||
options.tableName || options.modelName || options.name.plural
|
||||
}`;
|
||||
},
|
||||
},
|
||||
};
|
||||
return merge(defaults, config, options);
|
||||
}
|
||||
const database = `mock_${uid()}`;
|
||||
let dbExists = false;
|
||||
const defaults = {
|
||||
username: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_DATABASE,
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT as any,
|
||||
dialect: process.env.DB_DIALECT as any,
|
||||
logging: process.env.DB_LOG_SQL === 'on' ? console.log : false,
|
||||
dialectOptions: {
|
||||
charset: 'utf8mb4',
|
||||
collate: 'utf8mb4_unicode_ci',
|
||||
},
|
||||
hooks: {
|
||||
beforeDefine(model, options) {
|
||||
options.tableName = `${generatePrefixByPath()}_${
|
||||
options.tableName || options.modelName || options.name.plural
|
||||
}`;
|
||||
},
|
||||
async beforeSync({ sequelize }: any) {
|
||||
if (config.database) {
|
||||
return;
|
||||
}
|
||||
if (dbExists) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
const db = new Sequelize({
|
||||
username: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_DATABASE,
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT as any,
|
||||
dialect: process.env.DB_DIALECT as any,
|
||||
logging: process.env.DB_LOG_SQL === 'on' ? console.log : false,
|
||||
dialectOptions: {
|
||||
charset: 'utf8mb4',
|
||||
collate: 'utf8mb4_unicode_ci',
|
||||
},
|
||||
});
|
||||
await db.query(`CREATE DATABASE "${database}";`);
|
||||
await db.close();
|
||||
sequelize.options.database = database;
|
||||
sequelize.config.database = database;
|
||||
const ConnectionManager = sequelize.dialect.connectionManager.constructor;
|
||||
const connectionManager = new ConnectionManager(sequelize.dialect, sequelize);
|
||||
sequelize.dialect.connectionManager = connectionManager;
|
||||
sequelize.connectionManager = connectionManager;
|
||||
dbExists = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
return merge(defaults, config, options);
|
||||
}
|
||||
|
||||
export function mockDatabase(options?: DatabaseOptions): Database {
|
||||
return new Database(getConfig(options));
|
||||
}
|
||||
export { mockDatabase } from '../mock-database';
|
||||
|
@ -31,7 +31,11 @@ interface MapOf<T> {
|
||||
[key: string]: T;
|
||||
}
|
||||
|
||||
export type DatabaseOptions = Options | Sequelize;
|
||||
export interface IDatabaseOptions extends Options {
|
||||
tablePrefix?: string;
|
||||
}
|
||||
|
||||
export type DatabaseOptions = IDatabaseOptions | Sequelize;
|
||||
|
||||
interface RegisterOperatorsContext {
|
||||
db?: Database;
|
||||
@ -48,6 +52,7 @@ type OperatorFunc = (value: any, ctx?: RegisterOperatorsContext) => any;
|
||||
export class Database extends EventEmitter implements AsyncEmitter {
|
||||
sequelize: Sequelize;
|
||||
fieldTypes = new Map();
|
||||
options: IDatabaseOptions;
|
||||
models = new Map<string, ModelCtor<any>>();
|
||||
repositories = new Map<string, RepositoryType>();
|
||||
operators = new Map();
|
||||
@ -66,6 +71,7 @@ export class Database extends EventEmitter implements AsyncEmitter {
|
||||
this.sequelize = options;
|
||||
} else {
|
||||
this.sequelize = new Sequelize(options);
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
this.collections = new Map();
|
||||
@ -115,6 +121,10 @@ export class Database extends EventEmitter implements AsyncEmitter {
|
||||
return collection;
|
||||
}
|
||||
|
||||
getTablePrefix() {
|
||||
return this.options.tablePrefix || '';
|
||||
}
|
||||
|
||||
/**
|
||||
* get exists collection by its name
|
||||
* @param name
|
||||
|
@ -4,6 +4,7 @@ export * from './database';
|
||||
export { Database as default } from './database';
|
||||
export * from './fields';
|
||||
export * from './magic-attribute-model';
|
||||
export * from './mock-database';
|
||||
export * from './relation-repository/belongs-to-many-repository';
|
||||
export * from './relation-repository/belongs-to-repository';
|
||||
export * from './relation-repository/hasmany-repository';
|
||||
@ -12,4 +13,3 @@ export * from './relation-repository/single-relation-repository';
|
||||
export * from './repository';
|
||||
export * from './update-associations';
|
||||
|
||||
|
||||
|
37
packages/database/src/mock-database.ts
Normal file
37
packages/database/src/mock-database.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { merge, uid } from '@nocobase/utils';
|
||||
import { resolve } from 'path';
|
||||
import { Database, IDatabaseOptions } from './database';
|
||||
|
||||
export class MockDatabase extends Database {
|
||||
constructor(options: IDatabaseOptions) {
|
||||
super({
|
||||
storage: ':memory:',
|
||||
tablePrefix: `mock_${uid(6)}_`,
|
||||
...options,
|
||||
});
|
||||
this.sequelize.beforeDefine((model, opts) => {
|
||||
opts.tableName = `${this.getTablePrefix()}${opts.tableName || opts.modelName || opts.name.plural}`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getConfigByEnv() {
|
||||
return {
|
||||
username: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_DATABASE,
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT,
|
||||
dialect: process.env.DB_DIALECT,
|
||||
logging: process.env.DB_LOG_SQL === 'on' ? console.log : false,
|
||||
storage: process.env.DB_STORAGE ? resolve(process.cwd(), process.env.DB_STORAGE) : ':memory:',
|
||||
dialectOptions: {
|
||||
charset: 'utf8mb4',
|
||||
collate: 'utf8mb4_unicode_ci',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function mockDatabase(options: IDatabaseOptions = {}): MockDatabase {
|
||||
return new MockDatabase(merge(getConfigByEnv(), options));
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { ACL } from '@nocobase/acl';
|
||||
import { registerActions } from '@nocobase/actions';
|
||||
import Database, { CleanOptions, CollectionOptions, DatabaseOptions, SyncOptions } from '@nocobase/database';
|
||||
import Database, { CleanOptions, CollectionOptions, IDatabaseOptions, SyncOptions } from '@nocobase/database';
|
||||
import Resourcer, { ResourceOptions } from '@nocobase/resourcer';
|
||||
import { applyMixins, AsyncEmitter } from '@nocobase/utils';
|
||||
import { Command, CommandOptions } from 'commander';
|
||||
@ -18,7 +18,7 @@ export interface ResourcerOptions {
|
||||
}
|
||||
|
||||
export interface ApplicationOptions {
|
||||
database?: DatabaseOptions;
|
||||
database?: IDatabaseOptions | Database;
|
||||
resourcer?: ResourcerOptions;
|
||||
bodyParser?: any;
|
||||
cors?: any;
|
||||
|
@ -1,14 +0,0 @@
|
||||
import { mockDatabase } from '../';
|
||||
|
||||
describe('mock databasea', () => {
|
||||
it('mock databasea', async () => {
|
||||
const db = mockDatabase();
|
||||
db.collection({
|
||||
name: 'tests',
|
||||
fields: [{ type: 'string', name: 'name' }],
|
||||
});
|
||||
expect(db.getCollection('tests').model.getTableName()).toBe('_test_mockDatabase_tests');
|
||||
await db.sync();
|
||||
await db.close();
|
||||
});
|
||||
});
|
@ -1,34 +0,0 @@
|
||||
import { mockServer, MockServer } from '../';
|
||||
|
||||
describe('mock server', () => {
|
||||
let api: MockServer;
|
||||
|
||||
beforeEach(() => {
|
||||
api = mockServer({
|
||||
dataWrapping: false,
|
||||
});
|
||||
api.resourcer.registerActionHandlers({
|
||||
list: async (ctx, next) => {
|
||||
ctx.body = [1, 2];
|
||||
await next();
|
||||
},
|
||||
});
|
||||
api.resourcer.define({
|
||||
name: 'test',
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
return api.destroy();
|
||||
});
|
||||
|
||||
it('agent', async () => {
|
||||
const response = await api.agent().get('/test');
|
||||
expect(response.body).toEqual([1, 2]);
|
||||
});
|
||||
|
||||
it('resource', async () => {
|
||||
const response = await api.agent().resource('test').list();
|
||||
expect(response.body).toEqual([1, 2]);
|
||||
});
|
||||
});
|
@ -1,2 +1,3 @@
|
||||
export * from './mockDatabase';
|
||||
export { mockDatabase } from '@nocobase/database';
|
||||
export * from './mockServer';
|
||||
|
||||
|
@ -1,45 +0,0 @@
|
||||
import merge from 'deepmerge';
|
||||
import Database, { DatabaseOptions } from '@nocobase/database';
|
||||
|
||||
export function generatePrefixByPath() {
|
||||
const { id } = require.main;
|
||||
const key = id
|
||||
.replace(`${process.env.PWD}/packages`, '')
|
||||
.replace(/src\/__tests__/g, '')
|
||||
.replace('.test.ts', '')
|
||||
.replace(/[^\w]/g, '_')
|
||||
.replace(/_+/g, '_');
|
||||
return key;
|
||||
}
|
||||
|
||||
export function getConfig(config = {}, options?: any): DatabaseOptions {
|
||||
return merge(
|
||||
{
|
||||
username: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
storage: process.env.DB_STORAGE,
|
||||
database: process.env.DB_DATABASE,
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT,
|
||||
dialect: process.env.DB_DIALECT,
|
||||
logging: process.env.DB_LOG_SQL === 'on',
|
||||
sync: {
|
||||
force: true,
|
||||
alter: {
|
||||
drop: true,
|
||||
},
|
||||
},
|
||||
hooks: {
|
||||
beforeDefine(model, options) {
|
||||
options.tableName = `${generatePrefixByPath()}_${options.tableName || options.name.plural}`;
|
||||
},
|
||||
},
|
||||
},
|
||||
config || {},
|
||||
options,
|
||||
) as any;
|
||||
}
|
||||
|
||||
export function mockDatabase(options?: DatabaseOptions): Database {
|
||||
return new Database(getConfig(options));
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { mockDatabase } from '@nocobase/database';
|
||||
import Application, { ApplicationOptions } from '@nocobase/server';
|
||||
import qs from 'qs';
|
||||
import supertest, { SuperAgentTest } from 'supertest';
|
||||
import Application, { ApplicationOptions } from '@nocobase/server';
|
||||
import { getConfig } from './mockDatabase';
|
||||
|
||||
interface ActionParams {
|
||||
filterByTk?: any;
|
||||
@ -123,10 +123,11 @@ export class MockServer extends Application {
|
||||
}
|
||||
}
|
||||
|
||||
export function mockServer(options?: ApplicationOptions) {
|
||||
export function mockServer(options: ApplicationOptions = {}) {
|
||||
const database = mockDatabase((<any>options?.database) || {});
|
||||
return new MockServer({
|
||||
...options,
|
||||
database: getConfig(options?.database),
|
||||
database,
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user