import "reflect-metadata" import "../../utils/test-setup" import { expect } from "chai" import { Post } from "./entity/Post" import { Guest as GuestV1 } from "./entity/v1/Guest" import { Comment as CommentV1 } from "./entity/v1/Comment" import { Guest as GuestV2 } from "./entity/v2/Guest" import { Comment as CommentV2 } from "./entity/v2/Comment" import { View } from "./entity/View" import { Category } from "./entity/Category" import { closeTestingConnections, createTestingConnections, setupSingleTestingConnection, } from "../../utils/test-utils" import { DataSource } from "../../../src/data-source/DataSource" import { Repository } from "../../../src/repository/Repository" import { TreeRepository } from "../../../src/repository/TreeRepository" import { NoConnectionForRepositoryError } from "../../../src/error/NoConnectionForRepositoryError" import { EntityManager } from "../../../src/entity-manager/EntityManager" import { CannotGetEntityManagerNotConnectedError } from "../../../src/error/CannotGetEntityManagerNotConnectedError" import { PostgresConnectionOptions } from "../../../src/driver/postgres/PostgresConnectionOptions" describe("Connection", () => { // const resourceDir = __dirname + "/../../../../../test/functional/connection/"; describe("before connection is established", function () { let dataSource: DataSource before(async () => { const options = setupSingleTestingConnection("mysql", { name: "default", entities: [], }) if (!options) return dataSource = new DataSource(options) }) after(() => { if (dataSource && dataSource.isInitialized) return dataSource.destroy() return Promise.resolve() }) it("connection.isConnected should be false", () => { if (!dataSource) return dataSource.isInitialized.should.be.false }) it.skip("entity manager and reactive entity manager should not be accessible", () => { expect(() => dataSource.manager).to.throw( CannotGetEntityManagerNotConnectedError, ) // expect(() => connection.reactiveEntityManager).to.throw(CannotGetEntityManagerNotConnectedError); }) // todo: they aren't promises anymore /*it("import entities, entity schemas, subscribers and naming strategies should work", () => { return Promise.all([ connection.importEntities([Post]).should.be.fulfilled, connection.importEntitySchemas([]).should.be.fulfilled, connection.importSubscribers([]).should.be.fulfilled, connection.importNamingStrategies([]).should.be.fulfilled, connection.importEntitiesFromDirectories([]).should.be.fulfilled, connection.importEntitySchemaFromDirectories([]).should.be.fulfilled, connection.importSubscribersFromDirectories([]).should.be.fulfilled, connection.importNamingStrategiesFromDirectories([]).should.be.fulfilled ]); });*/ it("should not be able to close", () => { if (!dataSource) return return dataSource.close().should.be.rejected // CannotCloseNotConnectedError }) it("should not be able to sync a schema", () => { if (!dataSource) return return dataSource.synchronize().should.be.rejected // CannotCloseNotConnectedError }) it.skip("should not be able to use repositories", () => { if (!dataSource) return expect(() => dataSource.getRepository(Post)).to.throw( NoConnectionForRepositoryError, ) expect(() => dataSource.getTreeRepository(Category)).to.throw( NoConnectionForRepositoryError, ) // expect(() => connection.getReactiveRepository(Post)).to.throw(NoConnectionForRepositoryError); // expect(() => connection.getReactiveTreeRepository(Category)).to.throw(NoConnectionForRepositoryError); }) it("should be able to connect", () => { if (!dataSource) return return dataSource.connect().should.be.fulfilled }) }) describe.skip("establishing connection", function () { it("should throw DriverOptionNotSetError when extra.socketPath and host is missing", function () { expect(() => { new DataSource({ type: "mysql", username: "test", password: "test", database: "test", entities: [], dropSchema: false, }) }).to.throw(Error) }) }) describe("after connection is established successfully", function () { let connections: DataSource[] beforeEach(() => createTestingConnections({ entities: [Post, Category], schemaCreate: true, dropSchema: true, }).then((all) => (connections = all)), ) afterEach(() => closeTestingConnections(connections)) it("connection.isConnected should be true", () => connections.forEach((connection) => { connection.isInitialized.should.be.true })) it("entity manager and reactive entity manager should be accessible", () => connections.forEach((connection) => { expect(connection.manager).to.be.instanceOf(EntityManager) // expect(connection.reactiveEntityManager).to.be.instanceOf(ReactiveEntityManager); })) it("should not be able to connect again", () => connections.forEach((connection) => { return connection.connect().should.be.rejected // CannotConnectAlreadyConnectedError })) it("should be able to close a connection", async () => Promise.all( connections.map((connection) => { return connection.close() }), )) }) describe("working with repositories after connection is established successfully", function () { let connections: DataSource[] before(() => createTestingConnections({ entities: [Post, Category], schemaCreate: true, dropSchema: true, }).then((all) => (connections = all)), ) after(() => closeTestingConnections(connections)) it("should be able to get simple entity repository", () => connections.forEach((connection) => { connection.getRepository(Post).should.be.instanceOf(Repository) connection .getRepository(Post) .should.not.be.instanceOf(TreeRepository) connection.getRepository(Post).target.should.be.eql(Post) })) it("should be able to get tree entity repository", () => connections.forEach((connection) => { connection .getTreeRepository(Category) .should.be.instanceOf(TreeRepository) connection .getTreeRepository(Category) .target.should.be.eql(Category) })) // it("should be able to get simple entity reactive repository", () => connections.forEach(connection => { // connection.getReactiveRepository(Post).should.be.instanceOf(ReactiveRepository); // connection.getReactiveRepository(Post).should.not.be.instanceOf(TreeReactiveRepository); // connection.getReactiveRepository(Post).target.should.be.eql(Post); // })); // it("should be able to get tree entity reactive repository", () => connections.forEach(connection => { // connection.getReactiveTreeRepository(Category).should.be.instanceOf(TreeReactiveRepository); // connection.getReactiveTreeRepository(Category).target.should.be.eql(Category); // })); // it("should not be able to get tree entity repository of the non-tree entities", () => connections.forEach(connection => { // expect(() => connection.getTreeRepository(Post)).to.throw(Error); // RepositoryNotTreeError // // expect(() => connection.getReactiveTreeRepository(Post)).to.throw(RepositoryNotTreeError); // })); // it("should not be able to get repositories that are not registered", () => connections.forEach(connection => { // expect(() => connection.getRepository("SomeEntity")).to.throw(Error); // RepositoryNotTreeError // expect(() => connection.getTreeRepository("SomeEntity")).to.throw(Error); // RepositoryNotTreeError // // expect(() => connection.getReactiveRepository("SomeEntity")).to.throw(RepositoryNotFoundError); // // expect(() => connection.getReactiveTreeRepository("SomeEntity")).to.throw(RepositoryNotFoundError); // })); }) describe("generate a schema when connection.synchronize is called", function () { let connections: DataSource[] before(() => createTestingConnections({ entities: [Post], schemaCreate: true, dropSchema: true, }).then((all) => (connections = all)), ) after(() => closeTestingConnections(connections)) it("database should be empty after schema is synced with dropDatabase flag", () => Promise.all( connections.map(async (connection) => { const postRepository = connection.getRepository(Post) const post = new Post() post.title = "new post" await postRepository.save(post) const loadedPost = await postRepository.findOneBy({ id: post.id, }) expect(loadedPost).to.be.eql(post) await connection.synchronize(true) const againLoadedPost = await postRepository.findOneBy({ id: post.id, }) expect(againLoadedPost).to.be.null }), )) }) describe("log a schema when connection.logSyncSchema is called", function () { let connections: DataSource[] before( async () => (connections = await createTestingConnections({ entities: [Post], })), ) after(() => closeTestingConnections(connections)) it("should return sql log properly", () => Promise.all( connections.map(async (connection) => { await connection.driver.createSchemaBuilder().log() // console.log(sql); }), )) }) describe("after connection is closed successfully", function () { // open a close connections let connections: DataSource[] = [] before(() => createTestingConnections({ entities: [Post], schemaCreate: true, dropSchema: true, }).then((all) => { connections = all return Promise.all( connections.map((connection) => connection.close()), ) }), ) it("should not be able to close already closed connection", () => connections.forEach((connection) => { return connection.close().should.be.rejected // CannotCloseNotConnectedError })) it("connection.isConnected should be false", () => connections.forEach((connection) => { connection.isInitialized.should.be.false })) }) describe("skip schema generation when synchronize option is set to false", function () { let connections: DataSource[] beforeEach(() => createTestingConnections({ entities: [View], dropSchema: true, }).then((all) => (connections = all)), ) afterEach(() => closeTestingConnections(connections)) it("database should be empty after schema sync", () => Promise.all( connections.map(async (connection) => { await connection.synchronize(true) const queryRunner = connection.createQueryRunner() let schema = await queryRunner.getTables(["view"]) await queryRunner.release() expect(schema.some((table) => table.name === "view")).to.be .false }), )) }) describe("different names of the same content of the schema", () => { let connections: DataSource[] beforeEach(async () => { const connections1 = await createTestingConnections({ name: "test", enabledDrivers: ["postgres"], entities: [CommentV1, GuestV1], schema: "test-schema", dropSchema: true, }) const connections2 = await createTestingConnections({ name: "another", enabledDrivers: ["postgres"], entities: [CommentV1, GuestV1], schema: "another-schema", dropSchema: true, }) connections = [...connections1, ...connections2] }) after(() => closeTestingConnections(connections)) it("should not interfere with each other", async () => { await Promise.all(connections.map((c) => c.synchronize())) await closeTestingConnections(connections) const connections1 = await createTestingConnections({ name: "test", enabledDrivers: ["postgres"], entities: [CommentV2, GuestV2], schema: "test-schema", dropSchema: false, schemaCreate: true, }) const connections2 = await createTestingConnections({ name: "another", enabledDrivers: ["postgres"], entities: [CommentV2, GuestV2], schema: "another-schema", dropSchema: false, schemaCreate: true, }) connections = [...connections1, ...connections2] }) }) describe("can change postgres default schema name", () => { let connections: DataSource[] beforeEach(async () => { const connections1 = await createTestingConnections({ name: "test", enabledDrivers: ["postgres"], entities: [CommentV1, GuestV1], schema: "test-schema", dropSchema: true, }) const connections2 = await createTestingConnections({ name: "another", enabledDrivers: ["postgres"], entities: [CommentV1, GuestV1], schema: "another-schema", dropSchema: true, }) connections = [...connections1, ...connections2] }) afterEach(() => closeTestingConnections(connections)) it("schema name can be set", () => { return Promise.all( connections.map(async (connection) => { await connection.synchronize(true) const schemaName = ( connection.options as PostgresConnectionOptions ).schema const comment = new CommentV1() comment.title = "Change SchemaName" comment.context = `To ${schemaName}` const commentRepo = connection.getRepository(CommentV1) await commentRepo.save(comment) const queryRunner = connection.createQueryRunner() const rows = await queryRunner.query( `select * from "${schemaName}"."comment" where id = $1`, [comment.id], ) await queryRunner.release() expect(rows[0]["context"]).to.be.eq(comment.context) }), ) }) }) })