diff --git a/package.json b/package.json index c9791e5..f1342b2 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@types/chai": "^3.5.2", "@types/chai-as-promised": "0.0.30", "@types/mocha": "^2.2.41", + "@types/mock-fs": "^3.6.30", "@types/node": "^7.0.10", "@types/sinon": "^2.1.3", "chai": "^3.5.0", @@ -40,6 +41,7 @@ "codecov": "^2.1.0", "istanbul": "^0.4.5", "mocha": "^3.3.0", + "mock-fs": "^4.3.0", "remap-istanbul": "^0.9.5", "sinon": "^2.2.0", "sinon-chai": "^2.10.0", diff --git a/test/integration/examples/sample1-simple-entity/entity/Post.ts b/test/integration/examples/sample1-simple-entity/entity/Post.ts new file mode 100644 index 0000000..3aa5f65 --- /dev/null +++ b/test/integration/examples/sample1-simple-entity/entity/Post.ts @@ -0,0 +1,20 @@ +import {Column, Entity,PrimaryColumn,Index} from "typeorm"; + +@Entity("sample01_post") +export class Post { + + @PrimaryColumn("int", { generated: true }) + id: number; + + @Column() + title: string; + + @Column() + text: string; + + @Column("int", { + nullable: false + }) + likesCount: number; + +} \ No newline at end of file diff --git a/test/integration/integration.test.ts b/test/integration/integration.test.ts new file mode 100644 index 0000000..cdbf7b8 --- /dev/null +++ b/test/integration/integration.test.ts @@ -0,0 +1,85 @@ +import "reflect-metadata"; +import { createConnection, ConnectionOptions, Connection } from "typeorm"; +import { createTestingConnections, closeTestingConnections, reloadTestingDatabases } from "./../utils/test-utils" +import fs = require('fs'); +import path = require('path') +import { Post } from "./examples/sample1-simple-entity/entity/Post"; +import * as mockFS from "mock-fs"; +import { Engine } from "./../../src/Engine"; +import { AbstractDriver } from "./../../src/drivers/AbstractDriver"; +import { MssqlDriver } from "./../../src/drivers/MssqlDriver"; + +describe("integration tests", function () { + let connections: Connection[]; + + describe('should ...', async () => { + let examplesPath = path.resolve(__dirname, 'examples') + let files = fs.readdirSync(examplesPath) + // console.log(files) + files.forEach(folder => { + it(folder, async () => { + connections = await createTestingConnections({ + entities: [Post], + schemaCreate: true, + }) + await connections.forEach(async conn => { + + // conn.s + console.log('aa') + //TODO get model from db + await conn.entityManager.query(`select 'TODO'`)//depends on driver - remove tables + //compare models + if (conn.isConnected) + await conn.close() + let q=conn.isConnected + console.log(q) + + + let resultPath = path.resolve(__dirname, '../model') + mockFS({ resultPath: {} }) + + + var driver: AbstractDriver; + + driver = new MssqlDriver(); + let standardPort = 1433; + + let engine = new Engine( + driver, { + host: 'localhost', + port: standardPort, + databaseName: 'test', + user: 'sa', + password: 'password', + databaseType: 'mssql', + resultsPath: `test/model` + }); + + + let result = await engine.createModelFromDatabase() + console.log(result); + }); + + }) + + }); + }) + + // describe("sample1", async function () { + // connections = await createTestingConnections({ + // //entities: [Post], + // schemaCreate: false, + // }) + // await connections.forEach( async conn => { + // await conn.syncSchema() + // conn.entityManager.query('TODO')//depends on + // }); + // closeTestingConnections(connections) + + // //foreach driver + // //create model from db + // //compare models + + // }) +}); + diff --git a/test/utils/test-utils.ts b/test/utils/test-utils.ts new file mode 100644 index 0000000..6b901b0 --- /dev/null +++ b/test/utils/test-utils.ts @@ -0,0 +1,165 @@ +import { createConnection, createConnections, Connection, ConnectionOptions } from "typeorm"; + +export type DriverType = "mysql"|"postgres"|"mariadb"|"sqlite"|"oracle"|"mssql"|"websql"|"mongodb"; + +/** + * Interface in which data is stored in ormconfig.json of the project. + */ +export interface TestingConnectionOptions extends ConnectionOptions { + + /** + * Indicates if this connection should be skipped. + */ + skip?: boolean; + + /** + * If set to true then tests for this driver wont run until implicitly defined "enabledDrivers" section. + */ + disabledIfNotEnabledImplicitly?: boolean; + +} + +/** + * Options used to create a connection for testing purposes. + */ +export interface TestingOptions { + + /** + * Connection name to be overridden. + * This can be used to create multiple connections with single connection configuration. + */ + name?: string; + + /** + * List of enabled drivers for the given test suite. + */ + enabledDrivers?: DriverType[]; + + /** + * Entities needs to be included in the connection for the given test suite. + */ + entities?: string[] | Function[]; + + /** + * Subscribers needs to be included in the connection for the given test suite. + */ + subscribers?: string[] | Function[]; + + /** + * Indicates if schema sync should be performed or not. + */ + schemaCreate?: boolean; + + /** + * Indicates if schema should be dropped on connection setup. + */ + dropSchemaOnConnection?: boolean; + + /** + * Schema name used for postgres driver. + */ + schemaName?: string; + +} + +/** + * Creates a testing connection options for the given driver type based on the configuration in the ormconfig.json + * and given options that can override some of its configuration for the test-specific use case. + */ +export function setupSingleTestingConnection(driverType: DriverType, options: TestingOptions) { + + const testingConnections = setupTestingConnections({ + name: options.name ? options.name : undefined, + entities: options.entities ? options.entities : [], + subscribers: options.subscribers ? options.subscribers : [], + dropSchemaOnConnection: options.dropSchemaOnConnection ? options.dropSchemaOnConnection : false, + schemaCreate: options.schemaCreate ? options.schemaCreate : false, + enabledDrivers: [driverType], + schemaName: options.schemaName ? options.schemaName : undefined + }); + if (!testingConnections.length) + throw new Error(`Unable to run tests because connection options for "${driverType}" are not set.`); + + return testingConnections[0]; +} + + +/** + * Loads test connection options from ormconfig.json file. + */ +export function getTypeOrmConfig(): TestingConnectionOptions[] { + + try { + return require(__dirname + "/../../ormconfig.json"); + + } catch (err) { + throw new Error(`Cannot find ormconfig.json file in the root of the project. To run tests please create ormconfig.json file` + + ` in the root of the project (near ormconfig.json.dist, you need to copy ormconfig.json.dist into ormconfig.json` + + ` and change all database settings to match your local environment settings).`); + } +} + +/** + * Creates a testing connections options based on the configuration in the ormconfig.json + * and given options that can override some of its configuration for the test-specific use case. + */ +export function setupTestingConnections(options?: TestingOptions) { + const ormConfigConnectionOptionsArray = getTypeOrmConfig(); + + if (!ormConfigConnectionOptionsArray.length) + throw new Error(`No connections setup in ormconfig.json file. Please create configurations for each database type to run tests.`); + + return ormConfigConnectionOptionsArray + .filter(connectionOptions => { + if (connectionOptions.skip === true) + return false; + + if (options && options.enabledDrivers && options.enabledDrivers.length) + return options.enabledDrivers.indexOf(connectionOptions.driver.type) !== -1; + + if (connectionOptions.disabledIfNotEnabledImplicitly === true) + return false; + + return true; + }) + .map(connectionOptions => { + const newConnectionOptions = Object.assign({}, connectionOptions as ConnectionOptions, { + name: options && options.name ? options.name : connectionOptions.name, + entities: options && options.entities ? options.entities : [], + subscribers: options && options.subscribers ? options.subscribers : [], + autoSchemaSync: options && options.entities ? options.schemaCreate : false, + dropSchemaOnConnection: options && options.entities ? options.dropSchemaOnConnection : false, + }); + + + if (options && options.schemaName && newConnectionOptions.driver) { + // todo: we use any because driver.schemaName is readonly. Need to find better solution here + (newConnectionOptions.driver as any).schemaName = options.schemaName; + } + + return newConnectionOptions; + }); +} + +/** + * Creates a testing connections based on the configuration in the ormconfig.json + * and given options that can override some of its configuration for the test-specific use case. + */ +export async function createTestingConnections(options?: TestingOptions): Promise { + return createConnections(setupTestingConnections(options)); +} + +/** + * Closes testing connections if they are connected. + */ +export function closeTestingConnections(connections: Connection[]) { + return Promise.all(connections.map(connection => connection.isConnected ? connection.close() : undefined)); +} + +/** + * Reloads all databases for all given connections. + */ +export function reloadTestingDatabases(connections: Connection[]) { + return Promise.all(connections.map(connection => connection.syncSchema(true))); +} +