diff --git a/deployment/develop/docker/docker-compose.yaml b/deployment/develop/docker/docker-compose.yaml index b44e801..fc74787 100644 --- a/deployment/develop/docker/docker-compose.yaml +++ b/deployment/develop/docker/docker-compose.yaml @@ -54,24 +54,6 @@ services: - "traefik.http.routers.sf-nfc-server-secure.entrypoints=websecure" - "traefik.http.routers.sf-nfc-server-secure.rule=Host(`sf-nfc-server.savefamilygps.net`)" - "traefik.http.routers.sf-nfc-server-secure.tls=true" - - "traefik.http.routers.sf-nfc-server-secure.service=sf-sims" - - "traefik.http.routers.sf-nfc-server-secure.tls.certresolver=myresolver" + - "traefik.http.routers.sf-nfc-server-secure.service=sf-nfc-server" - "traefik.http.services.sf-nfc-server.loadbalancer.server.port=${PORT}" - "traefik.docker.network=proxy" - - postgresql-nfc: - container_name: postgresql-nfc - image: postgres:16.1 - env_file: - - .env - ports: - - "${POSTGRES_PORT}:5432" - volumes: - - ./sql-data/:/var/lib/postgres/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] - interval: 5s - retries: 5 - start_period: 5s - timeout: 5s - command: -p 5432 diff --git a/package.json b/package.json index fbd84f2..da4746e 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "index.js", "type": "module", "scripts": { - "test": "tsx --test --watch", + "test": "tsx --test", + "test:node": "node --import tsx --test --test-reporter spec --test-force-exit", "dev": "tsx src/main.ts", "build": "tsc", "build:esbuild": "esbuild --bundle src/main.ts --outdir=dist --platform=node --format=esm --packages=external", diff --git a/src/aplication/Nfc.usecases.test.ts b/src/aplication/Nfc.usecases.test.ts index f6791db..3ae31f5 100644 --- a/src/aplication/Nfc.usecases.test.ts +++ b/src/aplication/Nfc.usecases.test.ts @@ -12,7 +12,10 @@ describe("NFC activation code (Private methods)", () => { HttpClient: httpclient } - const nfcUsecases = new NfcUsecases(serverContext, {} as NfcRepository) + const nfcUsecases = new NfcUsecases({ + serverContext: serverContext, + nfcRepository: {} as NfcRepository + }) test("Should generate 8 digit codes", () => { // @ts-expect-error @@ -29,7 +32,6 @@ describe("NFC activation code (Private methods)", () => { const validation = nfcUsecases.validateActivationCode({ code }) - console.log("Codigo, validation", code, validation) assert(validation == true) }) @@ -60,7 +62,10 @@ describe("NfcUsecases Unit Tests (Public methods with Mocks)", () => { HttpClient: {} as any, }; - nfcUsecases = new NfcUsecases(mockServerContext, mockNfcRepository as unknown as NfcRepository); + nfcUsecases = new NfcUsecases({ + serverContext: mockServerContext, + nfcRepository: mockNfcRepository as unknown as NfcRepository + }); }); describe("generateActivationLabel", () => { @@ -100,10 +105,16 @@ describe("NfcUsecases Unit Tests (Public methods with Mocks)", () => { }); test("should generate new code if no existing codes found", async () => { + + const newCode = "v1234567"; mockNfcRepository.findActivationCodes.mock.mockImplementation(async () => ({ data: [] })); + mockNfcRepository.createActivationCode.mock.mockImplementation(async () => ({ + data: { card_id, code_plain: newCode } + })); + const usecase = nfcUsecases.generateActivationLabel(); const result = await usecase({ card_id }); @@ -115,10 +126,16 @@ describe("NfcUsecases Unit Tests (Public methods with Mocks)", () => { test("should generate new code if override is true even if existing codes exist", async () => { const existingCode = "v1234567"; + const newCode = "v89101112"; + mockNfcRepository.findActivationCodes.mock.mockImplementation(async () => ({ data: [{ code_plain: existingCode }] })); + mockNfcRepository.createActivationCode.mock.mockImplementation(async () => ({ + data: { card_id, code_plain: newCode } + })); + const usecase = nfcUsecases.generateActivationLabel(); const result = await usecase({ card_id, override: true }); diff --git a/src/aplication/Nfc.usecases.ts b/src/aplication/Nfc.usecases.ts index 0200030..a3901a8 100644 --- a/src/aplication/Nfc.usecases.ts +++ b/src/aplication/Nfc.usecases.ts @@ -89,7 +89,6 @@ export class NfcUsecases { override?: boolean, }): Promise> => { const generatedCodes = await this.nfcRepository.findActivationCodes(args.card_id) - if (generatedCodes.error != undefined) { console.error(generatedCodes.error) return generatedCodes // Caso de error diff --git a/src/infrastructure/Nfc.repository.test.ts b/src/infrastructure/Nfc.repository.test.ts index ab660aa..4b6ed32 100644 --- a/src/infrastructure/Nfc.repository.test.ts +++ b/src/infrastructure/Nfc.repository.test.ts @@ -1,12 +1,12 @@ import test, { describe, before, after } from "node:test"; -import assert from "node:assert"; +import assert from "node:assert/strict"; import { httpclient } from "config/httpclient.config.js"; import { pgClient } from "config/pgclient.config.js"; import { NfcRepository } from "./Nfc.repository.js"; import type { ServerContext } from "domain/ServerContext.js"; import { uuidv7 } from "uuidv7"; -describe("NfcRepository Integration Tests", () => { +await describe("NfcRepository Integration Tests", async () => { const serverContext: ServerContext = { PostgresClient: pgClient, HttpClient: httpclient @@ -16,6 +16,8 @@ describe("NfcRepository Integration Tests", () => { const testCardId = uuidv7() const testCode = "12345678"; + let lastCodeGenerated: string | undefined = undefined; + // Clean up before and after tests to ensure isolation const cleanup = async () => { await pgClient.query("DELETE FROM activation_codes WHERE card_id = $1", [testCardId]); @@ -29,7 +31,7 @@ describe("NfcRepository Integration Tests", () => { await cleanup(); }); - test("createActivationCode should insert a record into the database", async () => { + await test("createActivationCode should insert a record into the database", async () => { const result = await repo.createActivationCode({ cardId: testCardId, code: testCode @@ -43,9 +45,11 @@ describe("NfcRepository Integration Tests", () => { assert.strictEqual(result.data.card_id, testCardId); assert.strictEqual(result.data.code_plain, testCode); assert.ok(result.data.code_hash, "Hash should be generated"); + + lastCodeGenerated = result.data.code_plain; }); - test("findActivationCodes should retrieve the inserted record", async () => { + await test("findActivationCodes should retrieve the inserted record", async () => { // We assume the previous test inserted the record, but lets be safe or just rely on sequence const result = await repo.findActivationCodes(testCardId); @@ -61,7 +65,7 @@ describe("NfcRepository Integration Tests", () => { assert.strictEqual(found.card_id, testCardId); }); - test("findActivationCodes should return empty array if card has no codes", async () => { + await test("findActivationCodes should return empty array if card has no codes", async () => { const nonExistentCard = uuidv7() const result = await repo.findActivationCodes(nonExistentCard); @@ -73,4 +77,50 @@ describe("NfcRepository Integration Tests", () => { assert.ok(result.data, "Data should be returned"); assert.strictEqual(result.data.length, 0); }); + + await test("createActivationCode should add a new activation even if other exists", async () => { + const newCode = "secondcode" + const creation = await repo.createActivationCode({ + cardId: testCardId, + code: newCode, + }); + + const result = await repo.findActivationCodes(testCardId); + + if (result.error) { + assert.fail(`createActivationCode failed: ${result.error}`); + } + + assert.ok(result.error == undefined, "Creation must be sucessfull") + assert.ok(result.data, "Data must be non-empty") + + assert.ok(result.data, "Data should be returned"); + assert.ok(result.data.length > 1, "Code list should be at least 2"); + + const lastCode = result.data[0] + assert.ok(lastCode, "First value of the list shouldnt be undefined") + assert.strictEqual(lastCode.card_id, testCardId, `${lastCode.card_id} != ${testCardId}`); + assert.strictEqual(lastCode.code_plain, newCode, `${lastCode.code_plain} != ${newCode}`); + + lastCodeGenerated = newCode; + }); + + await test("findActivationCodes should return the last valid code first", async () => { + // We assume the previous test inserted the record, but lets be safe or just rely on sequence + const result = await repo.findActivationCodes(testCardId); + + if (result.error) { + assert.fail(`findActivationCodes failed: ${result.error}`); + } + + assert.ok(result.data, "Data should be returned"); + + assert.ok(Array.isArray(result.data)); + + const first = result.data[0]; + assert.ok(first, "At least 1 code should exist"); + assert.strictEqual(first.card_id, testCardId); + assert.strictEqual(first.code_plain, lastCodeGenerated); + }) }); + diff --git a/src/infrastructure/Nfc.repository.ts b/src/infrastructure/Nfc.repository.ts index 2943777..6e6eae4 100644 --- a/src/infrastructure/Nfc.repository.ts +++ b/src/infrastructure/Nfc.repository.ts @@ -19,6 +19,7 @@ export class NfcRepository { const query = ` SELECT * FROM activation_codes WHERE card_id = $1 + ORDER by code_id DESC ` const values = [cardId] try { @@ -64,6 +65,8 @@ export class NfcRepository { return { error: e as string } + } finally { + conn.release() } }