import sinon from "sinon" import { DataSource } from "../../../src/data-source/DataSource" import { createTestingConnections, closeTestingConnections, reloadTestingDatabases, } from "../../utils/test-utils" import { EntityManager, QueryRunner, SimpleConsoleLogger } from "../../../src" import { Foo } from "./entity/Foo" import { expect } from "chai" describe("github issues > #2216 - Ability to capture Postgres notifications in logger", () => { let connections: DataSource[] let queryRunner: QueryRunner let manager: EntityManager let logInfoStub: sinon.SinonStub before(() => { logInfoStub = sinon.stub(SimpleConsoleLogger.prototype, "log") }) beforeEach(async () => { await reloadTestingDatabases(connections) }) afterEach(() => logInfoStub.resetHistory()) after(() => logInfoStub.restore()) describe("when logNotifications option is NOT enabled", () => { before(async () => { connections = await createTestingConnections({ enabledDrivers: ["postgres"], entities: [Foo], createLogger: () => new SimpleConsoleLogger(), }) }) after(() => closeTestingConnections(connections)) it("should NOT pass extension setup notices to client", async () => Promise.all( connections.map(async (connection) => { sinon.assert.neverCalledWith( logInfoStub, "info", `extension "uuid-ossp" already exists, skipping`, ) sinon.assert.neverCalledWith( logInfoStub, "info", `extension "citext" already exists, skipping`, ) }), )) it("should NOT pass manual notices to client", async () => Promise.all( connections.map(async (connection) => { queryRunner = connection.createQueryRunner() await queryRunner.query( `DO $do$ BEGIN RAISE NOTICE 'this is a notice'; END $do$`, ) sinon.assert.neverCalledWith( logInfoStub, "info", "this is a notice", ) await queryRunner.release() }), )) it("should NOT pass 'listen -> notify' messages to client", async () => Promise.all( connections.map(async (connection) => { queryRunner = connection.createQueryRunner() await queryRunner.query("LISTEN foo;") await queryRunner.query("NOTIFY foo, 'bar!'") sinon.assert.neverCalledWith( logInfoStub, "info", "Received NOTIFY on channel foo: bar!.", ) await queryRunner.release() }), )) }) describe("when logNotifications option is enabled", () => { before(async () => { connections = await createTestingConnections({ enabledDrivers: ["postgres"], entities: [Foo], createLogger: () => new SimpleConsoleLogger(), driverSpecific: { logNotifications: true }, }) }) after(() => closeTestingConnections(connections)) it("should pass extension setup notices to client", async () => Promise.all( connections.map(async (connection) => { sinon.assert.calledWith( logInfoStub, "info", `extension "uuid-ossp" already exists, skipping`, ) sinon.assert.calledWith( logInfoStub, "info", `extension "citext" already exists, skipping`, ) }), )) it("should pass manual notices to client", async () => Promise.all( connections.map(async (connection) => { queryRunner = connection.createQueryRunner() await queryRunner.query( `DO $do$ BEGIN RAISE NOTICE 'this is a notice'; END $do$`, ) sinon.assert.calledWith( logInfoStub, "info", "this is a notice", ) await queryRunner.release() }), )) it("should pass 'listen -> notify' messages to client", async () => Promise.all( connections.map(async (connection) => { queryRunner = connection.createQueryRunner() await queryRunner.query("LISTEN foo;") await queryRunner.query("NOTIFY foo, 'bar!'") sinon.assert.calledWith( logInfoStub, "info", "Received NOTIFY on channel foo: bar!.", ) await queryRunner.release() }), )) it("should not interfere with actual queries", async () => Promise.all( connections.map(async (connection) => { manager = connection.manager const foo = new Foo() await manager.save( Object.assign(foo, { lowercaseval: "foo", lowercaseval2: "bar", }), ) const loadedFoo = await manager.findOneBy(Foo, { uuid: foo.uuid, }) expect(loadedFoo).not.to.be.null expect(loadedFoo).to.contain({ lowercaseval: "foo", lowercaseval2: "bar", }) }), )) }) })