diff --git a/package-lock.json b/package-lock.json index 25396e6..511b89c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,7 +32,6 @@ "jwt-decode": "^3.1.2", "pg": "^8.11.3", "redis": "^4.6.10", - "sinon": "^17.0.1", "source-map-support": "^0.5.21", "swagger-ui-dist": "^5.9.0", "swagger-ui-express": "^5.0.0", @@ -83,11 +82,12 @@ "husky": "^8.0.3", "lodash.kebabcase": "^4.1.1", "mocha": "^10.2.0", - "nock": "^13.3.4", + "nock": "^13.5.4", "nyc": "^15.1.0", "plop": "^4.0.0", "prettier": "^3.0.3", - "supertest": "^6.3.3", + "sinon": "^17.0.1", + "supertest": "^6.3.4", "typescript": "^5.2.2" }, "engines": { @@ -3692,6 +3692,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, "dependencies": { "type-detect": "4.0.8" } @@ -3700,6 +3701,7 @@ "version": "11.2.2", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", + "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0" } @@ -3708,6 +3710,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", + "dev": true, "dependencies": { "@sinonjs/commons": "^2.0.0", "lodash.get": "^4.4.2", @@ -3718,6 +3721,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, "dependencies": { "type-detect": "4.0.8" } @@ -3725,7 +3729,8 @@ "node_modules/@sinonjs/text-encoding": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==" + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", + "dev": true }, "node_modules/@sqltools/formatter": { "version": "1.2.5", @@ -10295,7 +10300,8 @@ "node_modules/just-extend": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", - "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==" + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", + "dev": true }, "node_modules/jwa": { "version": "1.4.1", @@ -10461,7 +10467,8 @@ "node_modules/lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true }, "node_modules/lodash.includes": { "version": "4.3.0", @@ -11203,6 +11210,7 @@ "version": "5.1.9", "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", + "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", "@sinonjs/fake-timers": "^11.2.2", @@ -11214,7 +11222,8 @@ "node_modules/nise/node_modules/path-to-regexp": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==" + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "dev": true }, "node_modules/no-case": { "version": "3.0.4", @@ -13641,6 +13650,7 @@ "version": "17.0.1", "resolved": "https://registry.npmjs.org/sinon/-/sinon-17.0.1.tgz", "integrity": "sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==", + "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", "@sinonjs/fake-timers": "^11.2.2", @@ -13658,6 +13668,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true, "engines": { "node": ">=0.3.1" } @@ -13666,6 +13677,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -14570,6 +14582,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, "engines": { "node": ">=4" } diff --git a/package.json b/package.json index 7b65070..749c23b 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,6 @@ "jwt-decode": "^3.1.2", "pg": "^8.11.3", "redis": "^4.6.10", - "sinon": "^17.0.1", "source-map-support": "^0.5.21", "swagger-ui-dist": "^5.9.0", "swagger-ui-express": "^5.0.0", @@ -110,11 +109,12 @@ "husky": "^8.0.3", "lodash.kebabcase": "^4.1.1", "mocha": "^10.2.0", - "nock": "^13.3.4", + "nock": "^13.5.4", "nyc": "^15.1.0", "plop": "^4.0.0", "prettier": "^3.0.3", - "supertest": "^6.3.3", + "sinon": "^17.0.1", + "supertest": "^6.3.4", "typescript": "^5.2.2" } } diff --git a/src/tests/bootstrap.ts b/src/tests/bootstrap.ts index 9bea3dd..3fd07aa 100644 --- a/src/tests/bootstrap.ts +++ b/src/tests/bootstrap.ts @@ -2,14 +2,28 @@ import "mocha"; import { use } from "chai"; import chaiAsPromised from "chai-as-promised"; import { DataSource } from "typeorm"; +import sinon from "sinon"; import "express-async-errors"; import { createContainer } from "../container"; import { config } from "../config/db"; import "express-async-errors"; +import * as auth0Module from "../middleware/auth0"; use(chaiAsPromised); -const clearDb = async (_dataSource: DataSource) => {}; +const clearDb = async (dataSource: DataSource) => { + const entities = dataSource.entityMetadatas; + + await dataSource.manager.transaction(async (transactionalEntityManager) => { + // disable checking relations + await transactionalEntityManager.query("SET session_replication_role = replica;"); + + await Promise.all(entities.map((entity) => transactionalEntityManager.query(`DELETE FROM "${entity.tableName}"`))); + + // enable checking relations + await transactionalEntityManager.query("SET session_replication_role = origin;"); + }); +}; before(async () => { const dbConnection = await new DataSource({ @@ -19,6 +33,20 @@ before(async () => { global.dbConnection = dbConnection; await dbConnection.dropDatabase(); + sinon.stub(auth0Module, "validateAccessToken").callsFake(() => (req, res, next) => { + // eslint-disable-next-line no-param-reassign + req.auth = { + payload: { + me: { + email: "test@integration.com", + }, + }, + header: {}, + token: "", + }; + + return next(); + }); global.container = await createContainer(); }); diff --git a/src/tests/shared/get-me.integration.spec.ts b/src/tests/shared/get-me.integration.spec.ts new file mode 100644 index 0000000..6bf4222 --- /dev/null +++ b/src/tests/shared/get-me.integration.spec.ts @@ -0,0 +1,33 @@ +import request from "supertest"; +import { StatusCodes } from "http-status-codes"; +import { expect } from "chai"; +import { dataSource } from "../../config/db"; +import { UserEntity } from "../../app/features/example/models/user.entity"; + +describe("GET /api/example/me", () => { + const authToken = "Bearer example.token"; + const userRepository = dataSource.getRepository(UserEntity); + + it("should return proper profile data", async () => { + const expectedUserEntity = await userRepository.save({ + firstName: "Test", + lastName: "Integration", + email: "test@integration.com", + }); + + await request(await global.container.cradle.app) + .get("/api/example/me") + .set("Authorization", authToken) + .expect(StatusCodes.OK) + .expect((response) => { + expect(response.body).to.deep.equal(expectedUserEntity); + }); + }); + + it("should return Not Found if there is no such user in database", async () => { + await request(await global.container.cradle.app) + .get("/api/example/me") + .set("Authorization", authToken) + .expect(StatusCodes.NOT_FOUND); + }); +});