├── tests ├── run.sh ├── index.ts ├── entities │ └── user.entity.ts ├── initialise-test-database.ts ├── entity-creation.spec.ts ├── rollback.spec.ts └── rollback-second-file.spec.ts ├── .dockerignore ├── src ├── exceptions │ └── rollback-error-exception.ts ├── index.ts ├── initialise.ts └── run-in-transaction.ts ├── devops └── testing │ ├── mysql-5 │ ├── my.cnf │ ├── env │ └── docker-compose.yaml │ ├── mysql-8 │ ├── my.cnf │ ├── env │ └── docker-compose.yaml │ ├── backend │ └── Dockerfile │ ├── postgres-10 │ ├── env │ └── docker-compose.yaml │ ├── postgres-11 │ ├── env │ └── docker-compose.yaml │ ├── postgres-12 │ ├── env │ └── docker-compose.yaml │ ├── postgres-13 │ ├── env │ └── docker-compose.yaml │ ├── postgres-9 │ ├── env │ └── docker-compose.yaml │ ├── mariadb-10 │ ├── env │ └── docker-compose.yaml │ └── run.sh ├── .prettierrc ├── .editorconfig ├── jest.config.js ├── .github └── workflows │ └── unit-tests.yaml ├── tsconfig.json ├── LICENSE ├── .gitignore ├── package.json ├── README.md └── CHANGELOG.md /tests/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /src/exceptions/rollback-error-exception.ts: -------------------------------------------------------------------------------- 1 | export class RollbackErrorException extends Error {} 2 | -------------------------------------------------------------------------------- /devops/testing/mysql-5/my.cnf: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | default-authentication-plugin=mysql_native_password 3 | user=mysql 4 | -------------------------------------------------------------------------------- /devops/testing/mysql-8/my.cnf: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | default_authentication_plugin=mysql_native_password 3 | user=mysql 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "tabWidth": 4, 5 | "semi": true, 6 | "bracketSpacing": true 7 | } 8 | -------------------------------------------------------------------------------- /tests/index.ts: -------------------------------------------------------------------------------- 1 | import { initialiseTestDatabase } from './initialise-test-database'; 2 | 3 | initialiseTestDatabase().then(() => process.exit(0)); 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | -------------------------------------------------------------------------------- /devops/testing/backend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts 2 | 3 | ENTRYPOINT ["npm"] 4 | CMD ["start"] 5 | 6 | WORKDIR /app 7 | 8 | COPY package*.json /app/ 9 | 10 | RUN npm install 11 | 12 | COPY . /app 13 | -------------------------------------------------------------------------------- /devops/testing/postgres-10/env: -------------------------------------------------------------------------------- 1 | POSTGRES_PASSWORD=transactions 2 | POSTGRES_USER=transactions 3 | POSTGRES_DB=transactions 4 | 5 | DB_USERNAME=transactions 6 | DB_PASSWORD=transactions 7 | DB_DATABASE=transactions 8 | DB_HOST=database 9 | DB_PORT=5432 10 | 11 | DB_TYPE=postgres 12 | -------------------------------------------------------------------------------- /devops/testing/postgres-11/env: -------------------------------------------------------------------------------- 1 | POSTGRES_PASSWORD=transactions 2 | POSTGRES_USER=transactions 3 | POSTGRES_DB=transactions 4 | 5 | DB_USERNAME=transactions 6 | DB_PASSWORD=transactions 7 | DB_DATABASE=transactions 8 | DB_HOST=database 9 | DB_PORT=5432 10 | 11 | DB_TYPE=postgres 12 | -------------------------------------------------------------------------------- /devops/testing/postgres-12/env: -------------------------------------------------------------------------------- 1 | POSTGRES_PASSWORD=transactions 2 | POSTGRES_USER=transactions 3 | POSTGRES_DB=transactions 4 | 5 | DB_USERNAME=transactions 6 | DB_PASSWORD=transactions 7 | DB_DATABASE=transactions 8 | DB_HOST=database 9 | DB_PORT=5432 10 | 11 | DB_TYPE=postgres 12 | -------------------------------------------------------------------------------- /devops/testing/postgres-13/env: -------------------------------------------------------------------------------- 1 | POSTGRES_PASSWORD=transactions 2 | POSTGRES_USER=transactions 3 | POSTGRES_DB=transactions 4 | 5 | DB_USERNAME=transactions 6 | DB_PASSWORD=transactions 7 | DB_DATABASE=transactions 8 | DB_HOST=database 9 | DB_PORT=5432 10 | 11 | DB_TYPE=postgres 12 | -------------------------------------------------------------------------------- /devops/testing/postgres-9/env: -------------------------------------------------------------------------------- 1 | POSTGRES_PASSWORD=transactions 2 | POSTGRES_USER=transactions 3 | POSTGRES_DB=transactions 4 | 5 | DB_USERNAME=transactions 6 | DB_PASSWORD=transactions 7 | DB_DATABASE=transactions 8 | DB_HOST=database 9 | DB_PORT=5432 10 | 11 | DB_TYPE=postgres 12 | -------------------------------------------------------------------------------- /devops/testing/mysql-5/env: -------------------------------------------------------------------------------- 1 | MYSQL_PASSWORD=transactions 2 | MYSQL_ALLOW_EMPTY_PASSWORD=1 3 | MYSQL_USER=transactions 4 | MYSQL_DATABASE=transactions 5 | 6 | DB_USERNAME=transactions 7 | DB_PASSWORD=transactions 8 | DB_DATABASE=transactions 9 | DB_HOST=database 10 | DB_PORT=3306 11 | 12 | DB_TYPE=mysql 13 | -------------------------------------------------------------------------------- /devops/testing/mysql-8/env: -------------------------------------------------------------------------------- 1 | MYSQL_PASSWORD=transactions 2 | MYSQL_ALLOW_EMPTY_PASSWORD=1 3 | MYSQL_USER=transactions 4 | MYSQL_DATABASE=transactions 5 | 6 | DB_USERNAME=transactions 7 | DB_PASSWORD=transactions 8 | DB_DATABASE=transactions 9 | DB_HOST=database 10 | DB_PORT=3306 11 | 12 | DB_TYPE=mysql 13 | -------------------------------------------------------------------------------- /devops/testing/mariadb-10/env: -------------------------------------------------------------------------------- 1 | MYSQL_PASSWORD=transactions 2 | MYSQL_ALLOW_EMPTY_PASSWORD=1 3 | MYSQL_USER=transactions 4 | MYSQL_DATABASE=transactions 5 | 6 | DB_USERNAME=transactions 7 | DB_PASSWORD=transactions 8 | DB_DATABASE=transactions 9 | DB_HOST=database 10 | DB_PORT=3306 11 | 12 | DB_TYPE=mysql 13 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "roots": [ 3 | "/src", 4 | "/tests" 5 | ], 6 | testMatch: [ 7 | "**/__tests__/**/*.+(ts|tsx|js)", 8 | "**/?(*.)+(spec|test).+(ts|tsx|js)" 9 | ], 10 | "transform": { 11 | "^.+\\.(ts|tsx)$": "ts-jest" 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /devops/testing/mariadb-10/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | database: 4 | image: mariadb:10.5 5 | env_file: 6 | - env 7 | 8 | tests: 9 | build: 10 | context: $PWD/../../.. 11 | dockerfile: $PWD/../backend/Dockerfile 12 | env_file: 13 | - env 14 | command: ['run', 'test'] 15 | -------------------------------------------------------------------------------- /devops/testing/postgres-9/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.6" 2 | services: 3 | database: 4 | image: postgres:9 5 | env_file: 6 | - ./env 7 | 8 | tests: 9 | build: 10 | context: $PWD/../../.. 11 | dockerfile: $PWD/../backend/Dockerfile 12 | env_file: 13 | - ./env 14 | command: ["run", "test"] 15 | -------------------------------------------------------------------------------- /devops/testing/postgres-10/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.6" 2 | services: 3 | database: 4 | image: postgres:10 5 | env_file: 6 | - ./env 7 | 8 | tests: 9 | build: 10 | context: $PWD/../../.. 11 | dockerfile: $PWD/../backend/Dockerfile 12 | env_file: 13 | - ./env 14 | command: ["run", "test"] 15 | -------------------------------------------------------------------------------- /devops/testing/postgres-11/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.6" 2 | services: 3 | database: 4 | image: postgres:11 5 | env_file: 6 | - ./env 7 | 8 | tests: 9 | build: 10 | context: $PWD/../../.. 11 | dockerfile: $PWD/../backend/Dockerfile 12 | env_file: 13 | - ./env 14 | command: ["run", "test"] 15 | -------------------------------------------------------------------------------- /devops/testing/postgres-12/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.6" 2 | services: 3 | database: 4 | image: postgres:12 5 | env_file: 6 | - ./env 7 | 8 | tests: 9 | build: 10 | context: $PWD/../../.. 11 | dockerfile: $PWD/../backend/Dockerfile 12 | env_file: 13 | - ./env 14 | command: ["run", "test"] 15 | -------------------------------------------------------------------------------- /devops/testing/postgres-13/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.6" 2 | services: 3 | database: 4 | image: postgres:13 5 | env_file: 6 | - ./env 7 | 8 | tests: 9 | build: 10 | context: $PWD/../../.. 11 | dockerfile: $PWD/../backend/Dockerfile 12 | env_file: 13 | - ./env 14 | command: ["run", "test"] 15 | -------------------------------------------------------------------------------- /.github/workflows/unit-tests.yaml: -------------------------------------------------------------------------------- 1 | name: Unit Tests 2 | 3 | on: 4 | push: 5 | branches: [develop, master] 6 | pull_request: 7 | branches: [develop] 8 | 9 | jobs: 10 | tests: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - name: Run the Unit Tests 16 | run: cd ./devops/testing && ./run.sh 17 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { initialiseTestTransactions } from './initialise'; 2 | import { RunFunction, runInTransaction, runInMultiConnectionTransaction } from './run-in-transaction'; 3 | 4 | export { 5 | initialiseTestTransactions, 6 | RunFunction, 7 | runInTransaction, 8 | runInTransaction as run, 9 | runInMultiConnectionTransaction, 10 | runInMultiConnectionTransaction as runMultiConnection 11 | }; 12 | -------------------------------------------------------------------------------- /src/initialise.ts: -------------------------------------------------------------------------------- 1 | import { 2 | initializeTransactionalContext, 3 | patchTypeORMRepositoryWithBaseRepository, 4 | } from 'typeorm-transactional-cls-hooked'; 5 | 6 | /** 7 | * Initialises the transaction context. See the reason for this at 8 | * https://github.com/odavid/typeorm-transactional-cls-hooked 9 | */ 10 | export function initialiseTestTransactions() { 11 | initializeTransactionalContext(); 12 | patchTypeORMRepositoryWithBaseRepository(); 13 | } 14 | -------------------------------------------------------------------------------- /tests/entities/user.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BaseEntity, 3 | Column, 4 | Entity, 5 | PrimaryGeneratedColumn, 6 | Unique, 7 | } from 'typeorm'; 8 | 9 | @Entity('users') 10 | @Unique(['email']) 11 | export class User extends BaseEntity { 12 | @PrimaryGeneratedColumn({ 13 | name: 'user_id', 14 | }) 15 | userId: number; 16 | 17 | @Column({ 18 | type: 'varchar', 19 | name: 'email', 20 | length: 128, 21 | }) 22 | email: string; 23 | } 24 | -------------------------------------------------------------------------------- /devops/testing/mysql-5/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.6" 2 | services: 3 | database: 4 | image: mysql/mysql-server:5.7 5 | command: --default-authentication-plugin=mysql_native_password 6 | env_file: 7 | - env 8 | volumes: 9 | - ./my.cnf:/etc/my.cnf 10 | 11 | tests: 12 | build: 13 | context: $PWD/../../.. 14 | dockerfile: $PWD/../backend/Dockerfile 15 | env_file: 16 | - env 17 | command: ["run", "test"] 18 | -------------------------------------------------------------------------------- /devops/testing/mysql-8/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | database: 4 | image: mysql/mysql-server:8.0 5 | command: --default-authentication-plugin=mysql_native_password 6 | env_file: 7 | - env 8 | volumes: 9 | - ./my.cnf:/etc/my.cnf 10 | 11 | tests: 12 | build: 13 | context: $PWD/../../.. 14 | dockerfile: $PWD/../backend/Dockerfile 15 | env_file: 16 | - env 17 | command: ['run', 'test'] 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "commonjs", 5 | "lib": ["es2017", "es7", "es6"], 6 | "declaration": true, 7 | "declarationMap": true, 8 | "sourceMap": true, 9 | "outDir": "./dist", 10 | "rootDir": "./src", 11 | "strict": true, 12 | "noImplicitAny": false, 13 | "strictNullChecks": false, 14 | "allowSyntheticDefaultImports": true, 15 | "esModuleInterop": true, 16 | "experimentalDecorators": true, 17 | "emitDecoratorMetadata": true, 18 | "skipLibCheck": true 19 | }, 20 | "exclude": ["node_modules", "dist", "tests"] 21 | } 22 | -------------------------------------------------------------------------------- /devops/testing/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Running transactional tests over multiple database versions..." 3 | echo "" 4 | echo "" 5 | 6 | ROOT=$(pwd) 7 | 8 | echo "Postgres 9" 9 | cd $ROOT/postgres-9 10 | docker-compose up --abort-on-container-exit 11 | 12 | echo "Postgres 10" 13 | cd $ROOT/postgres-10 14 | docker-compose up --abort-on-container-exit 15 | 16 | echo "Postgres 11" 17 | cd $ROOT/postgres-11 18 | docker-compose up --abort-on-container-exit 19 | 20 | echo "Postgres 12" 21 | cd $ROOT/postgres-12 22 | docker-compose up --abort-on-container-exit 23 | 24 | echo "Postgres 13" 25 | cd $ROOT/postgres-13 26 | docker-compose up --abort-on-container-exit 27 | 28 | echo "MySQL 5.7" 29 | cd $ROOT/mysql-5 30 | docker-compose up --abort-on-container-exit 31 | 32 | echo "MySQL 8" 33 | cd $ROOT/mysql-8 34 | docker-compose up --abort-on-container-exit 35 | 36 | echo "MariaDB 10" 37 | cd $ROOT/mariadb-10 38 | docker-compose up --abort-on-container-exit 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Entrostat (Pty) Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/initialise-test-database.ts: -------------------------------------------------------------------------------- 1 | import { Connection, createConnection } from 'typeorm'; 2 | import { User } from './entities/user.entity'; 3 | 4 | export async function initialiseTestDatabase() { 5 | return new Promise((resolve, reject) => { 6 | const connectionConfig = { 7 | type: process.env.DB_TYPE as any, 8 | host: process.env.DB_HOST, 9 | port: parseInt(process.env.DB_PORT, 10), 10 | username: process.env.DB_USERNAME, 11 | password: process.env.DB_PASSWORD, 12 | database: process.env.DB_DATABASE, 13 | entities: [User], 14 | synchronize: true, 15 | dropSchema: process.env.DB_INIT, 16 | logging: false, 17 | }; 18 | 19 | createConnection(connectionConfig as any) 20 | .then(connection => { 21 | // here you can start to work with your entities 22 | if (process.env.DB_INIT) { 23 | console.log(`Database initialised...`); 24 | } 25 | resolve(connection); 26 | }) 27 | .catch(error => reject(error)); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | .idea 64 | dist 65 | -------------------------------------------------------------------------------- /tests/entity-creation.spec.ts: -------------------------------------------------------------------------------- 1 | import { User } from './entities/user.entity'; 2 | import { Connection, QueryFailedError } from 'typeorm'; 3 | import { initialiseTestDatabase } from './initialise-test-database'; 4 | import { initialiseTestTransactions, runInTransaction } from '../src'; 5 | 6 | initialiseTestTransactions(); 7 | 8 | describe('entity creation', () => { 9 | let connection: Connection = null; 10 | 11 | beforeAll(async () => { 12 | connection = await initialiseTestDatabase(); 13 | }); 14 | 15 | afterAll(async () => { 16 | await connection.close(); 17 | }); 18 | 19 | it('allows for an entity to be created', runInTransaction(async () => { 20 | const email = 'entitycreation@gmail.com'; 21 | const user = User.create({ email }); 22 | 23 | await user.save(); 24 | 25 | const found = await User.findOne({ 26 | where: { email }, 27 | }); 28 | 29 | expect(found).toBeDefined(); 30 | })); 31 | 32 | it('fails if you try to create two of the same entity', runInTransaction(async () => { 33 | const email = 'uniqueconstraint@gmail.com'; 34 | const user = User.create({ email }); 35 | 36 | await user.save(); 37 | 38 | const found = await User.findOne({ 39 | where: { email }, 40 | }); 41 | 42 | expect(found).toBeDefined(); 43 | 44 | try { 45 | const sameUser = User.create({ email }); 46 | await sameUser.save(); 47 | } catch (e) { 48 | expect(e instanceof QueryFailedError).toBe(true); 49 | } 50 | })); 51 | }); 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typeorm-test-transactions", 3 | "version": "3.6.1", 4 | "description": "A transactional wrapper for tests that use TypeORM that automatically rolls back the transaction at the end of the test.", 5 | "main": "dist/index", 6 | "types": "dist/index", 7 | "scripts": { 8 | "pretest": "sleep 10; DB_INIT=1 ts-node tests/index.ts", 9 | "test": "jest --forceExit", 10 | "build": "rimraf dist && tsc", 11 | "prepublish": "npm run build", 12 | "release": "entro-version --during-release-post-hook=\"npm publish\"" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/entrostat/typeorm-test-transactions.git" 17 | }, 18 | "keywords": [ 19 | "typeorm", 20 | "transaction", 21 | "test", 22 | "rollback", 23 | "wrapper", 24 | "closure", 25 | "typescript" 26 | ], 27 | "author": "Kerren Ortlepp ", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/entrostat/typeorm-test-transactions/issues" 31 | }, 32 | "homepage": "https://github.com/entrostat/typeorm-test-transactions#readme", 33 | "devDependencies": { 34 | "@types/jest": "^27.0.2", 35 | "@types/node": "^16.10.1", 36 | "jest": "^27.2.2", 37 | "entro-version": "^1.5.0", 38 | "mysql": "^2.18.1", 39 | "pg": "^8.7.1", 40 | "prettier": "^2.4.1", 41 | "reflect-metadata": "^0.1.13", 42 | "rimraf": "^3.0.2", 43 | "standard-version": "^9.3.1", 44 | "ts-jest": "^27.0.5", 45 | "ts-node": "^10.2.1", 46 | "typeorm": "^0.2.37", 47 | "typescript": "^4.4.3" 48 | }, 49 | "dependencies": { 50 | "typeorm-transactional-cls-hooked": "^0.1.21" 51 | }, 52 | "standard-version": { 53 | "skip": { 54 | "tag": false 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tests/rollback.spec.ts: -------------------------------------------------------------------------------- 1 | import { User } from './entities/user.entity'; 2 | import { Connection } from 'typeorm'; 3 | import { runInTransaction, initialiseTestTransactions } from '../src'; 4 | import { initialiseTestDatabase } from './initialise-test-database'; 5 | 6 | initialiseTestTransactions(); 7 | 8 | describe('rollback tests', () => { 9 | let connection: Connection = null; 10 | 11 | beforeAll(async () => { 12 | connection = await initialiseTestDatabase(); 13 | }); 14 | 15 | afterAll(async () => { 16 | await connection.close(); 17 | }); 18 | 19 | it('rolls back the creation of an entity if it is wrapped in the transaction function', async () => { 20 | const email = 'sameuser@gmail.com'; 21 | await runInTransaction(async () => { 22 | const user = User.create({ email }); 23 | await user.save(); 24 | const found = await User.findOne({ 25 | where: { email }, 26 | }); 27 | expect(found).toBeDefined(); 28 | })(); 29 | 30 | await runInTransaction(async () => { 31 | const user = User.create({ email }); 32 | await user.save(); 33 | const found = await User.findOne({ 34 | where: { email }, 35 | }); 36 | expect(found).toBeDefined(); 37 | })(); 38 | }); 39 | 40 | it('rolls back multiple inserts', async () => { 41 | await runInTransaction(async () => { 42 | let email = 'user1@gmail.com'; 43 | await User.create({ email }).save(); 44 | let found = await User.findOne({ 45 | where: { email }, 46 | }); 47 | expect(found).toBeDefined(); 48 | 49 | email = 'user2@gmail.com'; 50 | await User.create({ email }).save(); 51 | found = await User.findOne({ 52 | where: { email }, 53 | }); 54 | expect(found).toBeDefined(); 55 | expect(await User.count()).toBe(2); 56 | })(); 57 | 58 | await runInTransaction(async () => { 59 | expect(await User.count()).toBe(0); 60 | })(); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /tests/rollback-second-file.spec.ts: -------------------------------------------------------------------------------- 1 | import { User } from './entities/user.entity'; 2 | import { Connection } from 'typeorm'; 3 | import { runInTransaction, initialiseTestTransactions } from '../src'; 4 | import { initialiseTestDatabase } from './initialise-test-database'; 5 | 6 | /** 7 | * The point of this file is to show that it still works even 8 | * when you initialise for the second time and run similar 9 | * (or in my case, the same) tests. 10 | */ 11 | 12 | initialiseTestTransactions(); 13 | 14 | describe('rollback tests - duplicated', () => { 15 | let connection: Connection = null; 16 | 17 | beforeAll(async () => { 18 | connection = await initialiseTestDatabase(); 19 | }); 20 | 21 | afterAll(async () => { 22 | await connection.close(); 23 | }); 24 | 25 | it('rolls back the creation of an entity if it is wrapped in the transaction function', async () => { 26 | const email = 'sameuser@gmail.com'; 27 | await runInTransaction(async () => { 28 | const user = User.create({ email }); 29 | await user.save(); 30 | const found = await User.findOne({ 31 | where: { email }, 32 | }); 33 | expect(found).toBeDefined(); 34 | })(); 35 | 36 | await runInTransaction(async () => { 37 | const user = User.create({ email }); 38 | await user.save(); 39 | const found = await User.findOne({ 40 | where: { email }, 41 | }); 42 | expect(found).toBeDefined(); 43 | })(); 44 | }); 45 | 46 | it('rolls back multiple inserts', async () => { 47 | await runInTransaction(async () => { 48 | let email = 'user1@gmail.com'; 49 | await User.create({ email }).save(); 50 | let found = await User.findOne({ 51 | where: { email }, 52 | }); 53 | expect(found).toBeDefined(); 54 | 55 | email = 'user2@gmail.com'; 56 | await User.create({ email }).save(); 57 | found = await User.findOne({ 58 | where: { email }, 59 | }); 60 | expect(found).toBeDefined(); 61 | 62 | expect(await User.count()).toBe(2); 63 | })(); 64 | 65 | await runInTransaction(async () => { 66 | expect(await User.count()).toBe(0); 67 | })(); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /src/run-in-transaction.ts: -------------------------------------------------------------------------------- 1 | import { Propagation, Transactional } from 'typeorm-transactional-cls-hooked'; 2 | import { RollbackErrorException } from './exceptions/rollback-error-exception'; 3 | import { createNamespace } from 'cls-hooked'; 4 | 5 | export type RunFunction = () => Promise | void; 6 | const scope = createNamespace('recursiveContext'); 7 | 8 | /** 9 | * Runs the code in a transaction and runs rollback on the transaction at the 10 | * end of it. 11 | * @param func The function you want run in a transaction 12 | */ 13 | export function runInTransaction(func: RunFunction) { 14 | return async () => { 15 | try { 16 | await TransactionCreator.run(func); 17 | } catch (e) { 18 | if (e instanceof RollbackErrorException) { 19 | // Do nothing here, the transaction has now been rolled back. 20 | } else { 21 | throw e; 22 | } 23 | } 24 | }; 25 | } 26 | 27 | /** 28 | * Runs a function in a nested transaction for each connection specified 29 | * @param connections The connections to run the transactions in 30 | * @param func The function you want run in a transaction 31 | * 32 | * Thanks @Dzeri96 for this contribution 33 | * https://github.com/Dzeri96/typeorm-test-transactions/tree/nested-transactions 34 | */ 35 | export function runInMultiConnectionTransaction( 36 | connections: string[], 37 | func: RunFunction, 38 | ) { 39 | return async () => { 40 | if (connections && connections.length != 0) { 41 | await scope.runPromise(async () => { 42 | scope.set('connections', connections); 43 | try { 44 | await TransactionCreator.runWithMultipleConnections(func); 45 | } catch (e) { 46 | if (e instanceof RollbackErrorException) { 47 | // Do nothing here, the transaction has now been rolled back. 48 | } else { 49 | throw e; 50 | } 51 | } 52 | }); 53 | } else { 54 | throw 'Connection array is empty. Consider using runInTransaction() instead.'; 55 | } 56 | }; 57 | } 58 | 59 | class TransactionCreator { 60 | @Transactional() 61 | static async run(func: RunFunction) { 62 | await func(); 63 | // Once the function has run, we throw an exception to ensure that the 64 | // transaction rolls back. 65 | throw new RollbackErrorException( 66 | `This is thrown to cause a rollback on the transaction.`, 67 | ); 68 | } 69 | 70 | @Transactional({ 71 | connectionName: () => scope.get('connections').pop(), 72 | propagation: Propagation.NESTED, 73 | }) 74 | static async runWithConnection(func: RunFunction) { 75 | await func(); 76 | // Once the function has run, we throw an exception to ensure that the 77 | // transaction rolls back. 78 | throw new RollbackErrorException( 79 | `This is thrown to cause a rollback on the transaction.`, 80 | ); 81 | } 82 | 83 | static async runWithMultipleConnections(func: RunFunction) { 84 | const connections: string[] = scope.get('connections') || []; 85 | if (connections.length != 0) { 86 | await TransactionCreator.runWithConnection( 87 | async () => 88 | await TransactionCreator.runWithMultipleConnections(func), 89 | ); 90 | } else { 91 | await TransactionCreator.runWithConnection(func); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TypeORM Test Transactions 2 | 3 | 4 | [![NPM](https://nodei.co/npm/typeorm-test-transactions.png)](https://nodei.co/npm/typeorm-test-transactions/) 5 | 6 | 7 | [![oclif](https://img.shields.io/badge/cli-oclif-brightgreen.svg?style=for-the-badge)](https://oclif.io) 8 | [![Version](https://img.shields.io/npm/v/typeorm-test-transactions.svg?style=for-the-badge)](https://npmjs.org/package/typeorm-test-transactions) 9 | [![Downloads/week](https://img.shields.io/npm/dw/typeorm-test-transactions.svg?style=for-the-badge)](https://npmjs.org/package/typeorm-test-transactions) 10 | [![License](https://img.shields.io/npm/l/typeorm-test-transactions.svg?style=for-the-badge)](https://github.com/entrostat/typeorm-test-transactions/blob/master/package.json) 11 | ![Build Status](https://github.com/entrostat/typeorm-test-transactions/actions/workflows/unit-tests.yaml/badge.svg) 12 | 13 | 14 | Have you wanted to run tests on a project that uses TypeORM directly on the database and in parallel? A lot of the time we can't do this because artefacts and data from other tests can affect the result of our current tests. What usually happens, in this case, is that our tests become quite complicated when database entities are involved because we need to track exact entities. Our `count()` and other aggregations must have `where` clauses so that we don't see results from other tests that have already completed. 15 | 16 | This library introduces a way to wrap tests in a transaction and automatically roll back the commits when the test ends. By doing this, you are able to run multiple tests concurrently and their data will not be seen by others. 17 | 18 | You may argue that we should mock out the entities and not use a database at all. This is a valid point, but sometimes we want to test database constraints and the effects they can have on application logic. 19 | 20 | ## Credit 21 | 22 | Before I start, I did not add much to get this to work. The major reason why this is possible is because of the work done by [odavid](https://github.com/odavid) in his [typeorm-transactional-cls-hooked](https://github.com/odavid/typeorm-transactional-cls-hooked) library. Thanks for the great work [odavid](https://github.com/odavid)! 23 | 24 | ## Limitations 25 | 26 | It has come to my attention that this library is **not** consistent if you use the `TypeORM` entity manager. So you'll want to use `typeorm-transactional-cls-hooked` to add the `@Transactional` decorator above function calls and those transactions will work correctly. What a colleague has found is that, when you use a `TypeORM` entity manager, they are independent of each other and data may still write to the database. 27 | 28 | ## Testing 29 | 30 | Currently, I have created a small test suite that tests that there is a rollback in the transaction wrapper. The goal is to test as many database versions as possible, currently I have: 31 | 32 | - MySQL 5.7 33 | - MySQL 8.0 34 | - MariaDB 10 35 | - Postgres 9 36 | - Postgres 10 37 | - Postgres 11 38 | - Postgres 12 39 | - Postgres 13 40 | 41 | The test badge represents tests that run over these databases: ![Build Status](https://github.com/entrostat/typeorm-test-transactions/actions/workflows/unit-tests.yaml/badge.svg) 42 | 43 | ## Getting Started 44 | 45 | In order to use this project you need to install the package, 46 | 47 | ```bash 48 | npm install --save typeorm-test-transactions 49 | 50 | # Not removing from the typeorm-transactional-cls-hooked 51 | # dependency separation. If you don't have the below 52 | # libraries then you'll need to install them as well 53 | # See https://github.com/odavid/typeorm-transactional-cls-hooked 54 | 55 | npm install --save typeorm reflect-metadata 56 | ``` 57 | 58 | When running your tests (I'm using `jest` and `nestjs` as the example), you'll want to wrap your test functions in the `runInTransaction` function. 59 | 60 | ```typescript 61 | import { 62 | runInTransaction, 63 | initialiseTestTransactions, 64 | } from 'typeorm-test-transactions'; 65 | import { DatabaseModule } from '@modules/database/database.module'; 66 | import { Test } from '@nestjs/testing'; 67 | 68 | initialiseTestTransactions(); 69 | 70 | describe('Feature1Test', () => { 71 | beforeEach(async () => { 72 | const module = await Test.createTestingModule({ 73 | imports: [DatabaseModule], 74 | }).compile(); 75 | }); 76 | 77 | describe('creation of 2 users', () => { 78 | it( 79 | 'should allow me to create multiple users if the email address is different but name is the same', 80 | runInTransaction(async () => { 81 | await User.create({ 82 | email: 'email1@test.com', 83 | name: 'Name', 84 | }).save(); 85 | 86 | await User.create({ 87 | email: 'email2@test.com', 88 | name: 'Name', 89 | }).save(); 90 | 91 | expect(await User.count()).toEqual(2); 92 | }), 93 | ); 94 | }); 95 | 96 | describe('creation of one of the users in previous step', () => { 97 | it( 98 | 'should allow me to create a user that is the same as the one in the previous step', 99 | runInTransaction(async () => { 100 | await User.create({ 101 | email: 'email1@test.com', 102 | name: 'Name', 103 | }).save(); 104 | 105 | expect(await User.count()).toEqual(1); 106 | }), 107 | ); 108 | }); 109 | }); 110 | ``` 111 | 112 | **IMPORTANT!** The example above wraps the entire test in a transaction and returns a function that `jest` executes. If you'd like to wrap *parts* of a test in a transaction, you need to **call** the function and `await` the result: 113 | ```typescript 114 | import { 115 | runInTransaction, 116 | initialiseTestTransactions, 117 | } from 'typeorm-test-transactions'; 118 | import { DatabaseModule } from '@modules/database/database.module'; 119 | import { Test } from '@nestjs/testing'; 120 | 121 | initialiseTestTransactions(); 122 | 123 | describe('Feature1Test', () => { 124 | beforeEach(async () => { 125 | const module = await Test.createTestingModule({ 126 | imports: [DatabaseModule], 127 | }).compile(); 128 | }); 129 | 130 | describe('creation of the same user in different sequential transactions', () => { 131 | it( 132 | 'allows me to create the same user twice if they were each in a transaction', 133 | async () => { 134 | await runInTransaction(async () => { 135 | await User.create({ 136 | email: 'email1@test.com', 137 | name: 'Name', 138 | }).save(); 139 | 140 | expect(await User.count()).toEqual(1); 141 | })(); 142 | await runInTransaction(async () => { 143 | await User.create({ 144 | email: 'email1@test.com', 145 | name: 'Name', 146 | }).save(); 147 | 148 | expect(await User.count()).toEqual(1); 149 | })(); 150 | } 151 | ); 152 | }); 153 | }); 154 | ``` 155 | 156 | ## Troubleshooting 157 | 158 | - There are some cases when the transactions don't roll back. So far, I've found the reason for that to be that the `typeorm` connection was started before this package was initialised. 159 | - I have seen an issue opened [typeorm-transactional-cls-hooked initialization #30](https://github.com/odavid/typeorm-transactional-cls-hooked/issues/30) where there may be a problem around where you perform the initialisation. Once I get feedback, I'll update the documentation here. 160 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [3.6.1](https://github.com/entrostat/typeorm-test-transactions/compare/v3.6.0...v3.6.1) (2021-09-26) 6 | 7 | 8 | ### Bug Fixes 9 | 10 | * **changelog:** Removed the useless entries in the changelog after fixing entro-version ([2bfce8a](https://github.com/entrostat/typeorm-test-transactions/commit/2bfce8aeae302ce3b4ac9eb1cf3fcf81c0c8d4c6)) 11 | 12 | ## [3.6.0](https://github.com/entrostat/typeorm-test-transactions/compare/v3.0.0...v3.6.0) (2021-09-26) 13 | 14 | 15 | ### Features 16 | 17 | * **build:** The build is working correctly, using entro-version to run a release ([0a6b0c2](https://github.com/entrostat/typeorm-test-transactions/commit/0a6b0c2e410bb2847edffe70c64654b9fd7b3b28)) 18 | * **versioning:** Added entro-version to the project ([e5fd464](https://github.com/entrostat/typeorm-test-transactions/commit/e5fd4646b4a0d057ccb363e5f85c873d5ef94606)) 19 | 20 | 21 | 22 | ### Bug Fixes 23 | 24 | * **build:** Don't checkout master before publishing because of entro-version ([34f1c6a](https://github.com/entrostat/typeorm-test-transactions/commit/34f1c6a6418d4e7eed2b75f20fc71d4d2ee5c6b2)) 25 | * **keywords:** Added typescript to the keywords ([7316cf3](https://github.com/entrostat/typeorm-test-transactions/commit/7316cf3e09229dcfc21faebc5dfd6e327a2eee40)) 26 | 27 | 28 | ## [3.0.0](https://github.com/entrostat/typeorm-test-transactions/compare/v2.0.0...v3.0.0) (2021-09-18) 29 | 30 | 31 | ### Features 32 | 33 | * **nested-transactions:** Added the ability to support multiple connections ([97f8058](https://github.com/entrostat/typeorm-test-transactions/commit/97f8058a98a91b8a834490d38662d95d983ad6c1)), closes [#25](https://github.com/entrostat/typeorm-test-transactions/issues/25) 34 | 35 | 36 | ### Bug Fixes 37 | 38 | * **formatting:** Changed the formatting and naming of functions to ensure that it's more readable ([24d4075](https://github.com/entrostat/typeorm-test-transactions/commit/24d40750aa7de7b4c10807b819d8b81c1679557a)) 39 | 40 | ## [1.4.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.3.0...v1.4.0) (2019-12-15) 41 | 42 | ## [1.3.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.2.3...v1.3.0) (2019-11-27) 43 | 44 | ## [2.0.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.14.3...v2.0.0) (2021-09-18) 45 | 46 | ### [1.14.3](https://github.com/entrostat/typeorm-test-transactions/compare/v1.14.2...v1.14.3) (2021-09-18) 47 | 48 | 49 | ### Bug Fixes 50 | 51 | * **devops:** Added a Github action to test Postgres 9 ([770e1f7](https://github.com/entrostat/typeorm-test-transactions/commit/770e1f7126008d9283581a5b7c72276a4d46d1c5)) 52 | * **devops:** Removed Travis-CI and plug into the Github Actions for testing ([4474296](https://github.com/entrostat/typeorm-test-transactions/commit/4474296ce6c7e18baf88a2682922c6e216ccae6c)) 53 | 54 | ### [1.14.2](https://github.com/entrostat/typeorm-test-transactions/compare/v1.14.1...v1.14.2) (2021-01-02) 55 | 56 | ### [1.14.1](https://github.com/entrostat/typeorm-test-transactions/compare/v1.14.0...v1.14.1) (2020-10-31) 57 | 58 | ## [1.14.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.13.0...v1.14.0) (2020-10-31) 59 | 60 | 61 | ### Features 62 | 63 | * **tests:** fixed major bugs on the tests ([1fe86f6](https://github.com/entrostat/typeorm-test-transactions/commit/1fe86f67d79955eb2712d446a9551f9d606f7ad8)) 64 | 65 | ## [1.13.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.12.1...v1.13.0) (2020-08-22) 66 | 67 | 68 | ### Features 69 | 70 | * **testing:** added tests for Postgres 13 ([62eb9e2](https://github.com/entrostat/typeorm-test-transactions/commit/62eb9e21925124f65ceca4b8c5200e4ebbdb61d1)), closes [#17](https://github.com/entrostat/typeorm-test-transactions/issues/17) 71 | 72 | ### [1.12.1](https://github.com/entrostat/typeorm-test-transactions/compare/v1.12.0...v1.12.1) (2020-08-22) 73 | 74 | ## [1.12.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.11.1...v1.12.0) (2020-08-22) 75 | 76 | 77 | ### Features 78 | 79 | * **testing:** added tests for mariadb 10 ([ffd3475](https://github.com/entrostat/typeorm-test-transactions/commit/ffd347558d1945fb37d0b2d6515cd1928121e69a)), closes [#15](https://github.com/entrostat/typeorm-test-transactions/issues/15) 80 | 81 | ### [1.11.1](https://github.com/entrostat/typeorm-test-transactions/compare/v1.11.0...v1.11.1) (2020-05-27) 82 | 83 | 84 | ### Bug Fixes 85 | 86 | * **deps:** updated npm packages ([ff1ef77](https://github.com/entrostat/typeorm-test-transactions/commit/ff1ef778d55abf09245fb193c1797e0ebe430978)), closes [#12](https://github.com/entrostat/typeorm-test-transactions/issues/12) 87 | 88 | ## [1.11.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.10.1...v1.11.0) (2020-05-27) 89 | 90 | ### Features 91 | 92 | - **testing:** added mysql 8 tests ([420223c](https://github.com/entrostat/typeorm-test-transactions/commit/420223c25e652daaef22d1dfadb31a790ebfa6d9)), closes [#11](https://github.com/entrostat/typeorm-test-transactions/issues/11) 93 | 94 | ### [1.10.1](https://github.com/entrostat/typeorm-test-transactions/compare/v1.10.0...v1.10.1) (2020-03-24) 95 | 96 | ## [1.10.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.9.1...v1.10.0) (2020-03-05) 97 | 98 | ### Features 99 | 100 | - **testing:** added a second test file to test any init problems ([181f542](https://github.com/entrostat/typeorm-test-transactions/commit/181f542d94d942fc644818120e41dfdb45d199ad)), closes [#8](https://github.com/entrostat/typeorm-test-transactions/issues/8) 101 | 102 | ### [1.9.1](https://github.com/entrostat/typeorm-test-transactions/compare/v1.9.0...v1.9.1) (2020-03-05) 103 | 104 | ### Bug Fixes 105 | 106 | - **testing:** I wasn't importing the initialise function (which I was doing in the docs) ([517f54d](https://github.com/entrostat/typeorm-test-transactions/commit/517f54df57136d511369a2fbc36d916b1cabcd67)) 107 | 108 | ## [1.9.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.8.1...v1.9.0) (2019-12-15) 109 | 110 | ### Features 111 | 112 | - **testing:** added tests for mysql 5.7 ([5d10190](https://github.com/entrostat/typeorm-test-transactions/commit/5d10190bf28f7b7534ea19c4861547bb8eec237b)) 113 | 114 | ### [1.8.1](https://github.com/entrostat/typeorm-test-transactions/compare/v1.8.0...v1.8.1) (2019-12-15) 115 | 116 | ### Bug Fixes 117 | 118 | - **formatting:** ran prettier on code ([8b5dc71](https://github.com/entrostat/typeorm-test-transactions/commit/8b5dc7165c80214fa9bdacce163395a475f465db)) 119 | 120 | ## [1.8.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.7.1...v1.8.0) (2019-12-15) 121 | 122 | ### Features 123 | 124 | - **testing:** added testing for postgres 9 ([ab09273](https://github.com/entrostat/typeorm-test-transactions/commit/ab09273d2c41b19b08943fa87337345660e7edb9)) 125 | - **testing:** added tests for postgres 10 ([d14baef](https://github.com/entrostat/typeorm-test-transactions/commit/d14baefda4e60d396e09ae821cb7283f4293883b)) 126 | 127 | ### [1.7.1](https://github.com/entrostat/typeorm-test-transactions/compare/v1.7.0...v1.7.1) (2019-12-15) 128 | 129 | ### Bug Fixes 130 | 131 | - **build:** exclude tests from tsc build ([5271325](https://github.com/entrostat/typeorm-test-transactions/commit/52713256bf037ce81f5fb65853e8a444789504a4)) 132 | 133 | ## [1.7.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.6.0...v1.7.0) (2019-12-15) 134 | 135 | ### Features 136 | 137 | - **testing:** added postgres 12 tests ([05f8ea4](https://github.com/entrostat/typeorm-test-transactions/commit/05f8ea4880d59d2e3993c8d16831ba12e81f33ef)) 138 | 139 | ## [1.6.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.5.0...v1.6.0) (2019-12-15) 140 | 141 | ### Features 142 | 143 | - **testing:** added travis-ci testing to the project so that we can test different databases ([4874a76](https://github.com/entrostat/typeorm-test-transactions/commit/4874a761922e50b62c8013c04a63eae20a708048)) 144 | 145 | ## [1.5.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.2.3...v1.5.0) (2019-12-15) 146 | 147 | ### Features 148 | 149 | - divide error case to support test that used the supertest module ([b5319e1](https://github.com/entrostat/typeorm-test-transactions/commit/b5319e14d9e635b8607f45f26639f2294d424b3d)) 150 | 151 | ### Bug Fixes 152 | 153 | - **convention:** named the files to fit convention ([ab76b7d](https://github.com/entrostat/typeorm-test-transactions/commit/ab76b7dd976d78ab0864c3f20dd9760d01dca78f)) 154 | - **convetion:** named the files to fit convention ([d2c8d43](https://github.com/entrostat/typeorm-test-transactions/commit/d2c8d4357460430764d0358bdd2f81c17bf16890)) 155 | - **exception:** only catch certain exceptions in the transaction wrapper so that other exceptions are not caught ([3f756df](https://github.com/entrostat/typeorm-test-transactions/commit/3f756dfb27ec180556aa94810e969a48e24c17a7)) 156 | - **semver:** let the standard version package tag releases ([ccd4b5b](https://github.com/entrostat/typeorm-test-transactions/commit/ccd4b5bfa70b63e32e5e6255a4a592f058f32b0d)) 157 | 158 | ## [1.4.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.2.3...v1.4.0) (2019-12-15) 159 | 160 | ### Features 161 | 162 | - divide error case to support test that used the supertest module ([b5319e1](https://github.com/entrostat/typeorm-test-transactions/commit/b5319e14d9e635b8607f45f26639f2294d424b3d)) 163 | 164 | ### Bug Fixes 165 | 166 | - **convention:** named the files to fit convention ([ab76b7d](https://github.com/entrostat/typeorm-test-transactions/commit/ab76b7dd976d78ab0864c3f20dd9760d01dca78f)) 167 | - **convetion:** named the files to fit convention ([d2c8d43](https://github.com/entrostat/typeorm-test-transactions/commit/d2c8d4357460430764d0358bdd2f81c17bf16890)) 168 | - **exception:** only catch certain exceptions in the transaction wrapper so that other exceptions are not caught ([3f756df](https://github.com/entrostat/typeorm-test-transactions/commit/3f756dfb27ec180556aa94810e969a48e24c17a7)) 169 | 170 | ## [1.3.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.2.3...v1.3.0) (2019-11-27) 171 | 172 | ### Features 173 | 174 | - divide error case to support test that used the supertest module ([b5319e1](https://github.com/entrostat/typeorm-test-transactions/commit/b5319e14d9e635b8607f45f26639f2294d424b3d)) 175 | 176 | ### Bug Fixes 177 | 178 | - **exception:** only catch certain exceptions in the transaction wrapper so that other exceptions are not caught ([3f756df](https://github.com/entrostat/typeorm-test-transactions/commit/3f756dfb27ec180556aa94810e969a48e24c17a7)) 179 | 180 | ### [1.2.3](https://github.com/entrostat/typeorm-test-transactions/compare/v1.2.1...v1.2.3) (2019-10-12) 181 | 182 | ### Bug Fixes 183 | 184 | - **exports:** aliased the functions so they use the same code ([9fe43a6](https://github.com/entrostat/typeorm-test-transactions/commit/9fe43a648c3a0c57899d32a76fb7c7f5d9581018)) 185 | 186 | ### [1.2.2](https://github.com/entrostat/typeorm-test-transactions/compare/v1.2.1...v1.2.2) (2019-10-12) 187 | 188 | ### Bug Fixes 189 | 190 | - **exports:** aliased the functions so they use the same code ([9fe43a6](https://github.com/entrostat/typeorm-test-transactions/commit/9fe43a648c3a0c57899d32a76fb7c7f5d9581018)) 191 | 192 | ### [1.2.1](https://github.com/entrostat/typeorm-test-transactions/compare/v1.2.0...v1.2.1) (2019-10-12) 193 | 194 | ### Bug Fixes 195 | 196 | - **semver:** don't tag the commits with standard versioning (I use git flow) ([1ef2a9e](https://github.com/entrostat/typeorm-test-transactions/commit/1ef2a9ecb11b6e6d3ef25351cb64500f0f97ebf3)) 197 | 198 | ## [1.2.0](https://github.com/entrostat/typeorm-test-transactions/compare/v1.1.3...v1.2.0) (2019-10-12) 199 | 200 | ### Features 201 | 202 | - **semver:** added the changelog file ([d0713a5](https://github.com/entrostat/typeorm-test-transactions/commit/d0713a5af96163133d28802d05b60451b4d08338)) 203 | - **semver:** added the standard versioning library ([fb656a2](https://github.com/entrostat/typeorm-test-transactions/commit/fb656a29e665105ce35c8051e00994ad0faa3fcc)) 204 | --------------------------------------------------------------------------------