diff --git a/.env.example b/.env.example index 4cdb5c0..23f3343 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,3 @@ DATABASE_URL="postgresql://postgres:docker@localhost:5432/daily-diet?schema=public" PORT=3000 +NODE_ENV=dev diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml new file mode 100644 index 0000000..3512204 --- /dev/null +++ b/.github/workflows/run-e2e-tests.yml @@ -0,0 +1,33 @@ +name: Run E2E Tests + +on: [pull_request] + +jobs: + run-e2e-tests: + name: Run E2E Tests + runs-on: ubuntu-latest + + services: + postgres: + image: bitnami/postgresql + ports: + - 5432:5432 + env: + POSTGRESQL_USERNAME: postgres + POSTGRESQL_PASSWORD: docker + POSTGRESQL_DATABASE: find-a-friend + + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-node@v3 + with: + node-version: 18 + cache: "npm" + + - run: npm ci + - run: npm run ci:gen-jwt-keys + + - run: npm run test:e2e + env: + DATABASE_URL: "postgresql://postgres:docker@localhost:5432/find-a-friend?schema=public" diff --git a/.github/workflows/run-unit-tests.yml b/.github/workflows/run-unit-tests.yml new file mode 100644 index 0000000..993c9a8 --- /dev/null +++ b/.github/workflows/run-unit-tests.yml @@ -0,0 +1,20 @@ +name: Run Unit Tests + +on: [push] + +jobs: + run-unit-tests: + name: Run Unit Tests + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-node@v3 + with: + node-version: 18 + cache: "npm" + + - run: npm ci + + - run: npm run test diff --git a/README.md b/README.md index 5e8f813..e494f46 100644 --- a/README.md +++ b/README.md @@ -72,42 +72,48 @@ A seguir estarão disponíveis as informações relacionadas ao desenvolvimento ### Requisitos Funcionais -- [ ] Deve ser possível cadastrar um pet -- [ ] Deve ser possível listar todos os pets disponíveis para adoção em uma cidade -- [ ] Deve ser possível filtrar pets por suas características -- [ ] Deve ser possível visualizar detalhes de um pet para adoção -- [ ] Deve ser possível se cadastrar como uma ORG -- [ ] Deve ser possível realizar login como uma ORG +- [x] Deve ser possível cadastrar um pet +- [x] Deve ser possível listar todos os pets disponíveis para adoção em uma cidade +- [x] Deve ser possível filtrar pets por suas características +- [x] Deve ser possível visualizar detalhes de um pet para adoção +- [x] Deve ser possível se cadastrar como uma ORG +- [x] Deve ser possível realizar login como uma ORG ### Regras de Negócio -- [ ] Para listar os pets, obrigatoriamente precisamos informar a cidade -- [ ] Uma ORG precisa ter um endereço e um número de WhatsApp -- [ ] Um pet deve estar ligado a uma ORG -- [ ] O usuário que quer adotar, entrará em contato com a ORG via WhatsApp -- [ ] Todos os filtros, além da cidade, são opcionais -- [ ] Para uma ORG acessar a aplicação como admin, ela precisa estar logada +- [x] Para listar os pets, obrigatoriamente precisamos informar a cidade +- [x] Uma ORG precisa ter um endereço e um número de WhatsApp +- [x] Um pet deve estar ligado a uma ORG +- [x] O usuário que quer adotar, entrará em contato com a ORG via WhatsApp +- [x] Todos os filtros, além da cidade, são opcionais +- [x] Para uma ORG acessar a aplicação como admin, ela precisa estar logada ### Requisitos Não Funcionais -- [ ] Os dados deverão ser persistidos num banco de dados postgreSQL -- [ ] O Banco de dados em desenvolvimento deve ser usado através de um container do Docker -- [ ] Devem haver testes unitários e testes e2e para validar os requisitos e as regras de negócio +- [x] Os dados deverão ser persistidos num banco de dados postgreSQL +- [x] O Banco de dados em desenvolvimento deve ser usado através de um container do Docker +- [x] Devem haver testes unitários e testes e2e para validar os requisitos e as regras de negócio - [ ] Deve ser implementado o CI (Continuous Integration) - [ ] CI - ao realizar um **push** para o github, todos os tests unitários devem ser executados - [ ] CI - ao realizar um **pull request** para o github, todos os tests e2e devem ser executados -- [ ] O projeto dev seguir a metodologia DDD (Domain-Driven Design) +- [x] O projeto dev seguir a metodologia DDD (Domain-Driven Design) ### Metodologia Domain-Driven Design -- [ ] domains: - - [ ] find a friend - - [ ] application - - [ ] repositories - - [ ] pets repository - - [ ] users repository - - [ ] enterprise - - [ ] entities: - - [ ] basic user - - [ ] org - - [ ] pet +- [x] domains: + - [x] find a friend: + - [x] application: + - [x] repositories: + - [x] pets repository + - [x] users repository + - [x] use cases: + - [x] register org + - [x] authenticate org + - [x] register pet + - [x] fetch all adoptable pet + - [x] find pet + - [x] want to adopt + - [x] enterprise: + - [x] entities: + - [x] org + - [x] pet diff --git a/client.http b/client.http index 381393b..323de3d 100644 --- a/client.http +++ b/client.http @@ -56,45 +56,14 @@ Authorization: Bearer {{authToken}} GET {{baseUrl}}/pets?city=the daily planet&mainCharacteristics=diurno,limpo&color=preto - -### - -# @name update_meal -PUT {{baseUrl}}/meals/49715768-da2f-49f5-9ff9-87a3d28ebcce -Content-Type: application/json -Authorization: Bearer {{authToken}} - -{ - "name": "meal test", - "description": "testing", - "isInDiet": false, - "dateTime": "2024-06-10T11:09:30.535Z" -} - - - -### - -# @name delete_meal -DELETE {{baseUrl}}/meals/0e42f8d8-33c2-4490-856e-fa59fd25000e -Content-Type: application/json -Authorization: Bearer {{authToken}} - - - - ### -# @name find_meal_by_id -GET {{baseUrl}}/meals/49715768-da2f-49f5-9ff9-87a3d28ebcce -Content-Type: application/json -Authorization: Bearer {{authToken}} +# @name find_pet +GET {{baseUrl}}/pets/b10f8cc7-b64c-4a85-a4b2-52d690b9417a ### -# @name get_user_metrics -GET {{baseUrl}}/meals/metrics -Content-Type: application/json -Authorization: Bearer {{authToken}} +# @name want_to_adopt_pet +GET {{baseUrl}}/pets/adopt/b10f8cc7-b64c-4a85-a4b2-52d690b9417a diff --git a/package-lock.json b/package-lock.json index 2519133..593ab75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,9 +23,12 @@ "@fakerjs/faker": "^3.0.0", "@types/bcryptjs": "^2.4.6", "@types/node": "^20.14.2", + "@types/supertest": "^6.0.2", "eslint": "^8.57.0", "eslint-plugin-vitest-globals": "^1.5.0", + "npm-run-all": "4.1.5", "prisma": "^5.15.0", + "supertest": "^7.0.0", "tsx": "^4.15.1", "typescript": "^5.4.5", "vite-tsconfig-paths": "^4.3.2", @@ -1307,6 +1310,12 @@ "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", "dev": true }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -1328,6 +1337,12 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true + }, "node_modules/@types/node": { "version": "20.14.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", @@ -1342,6 +1357,27 @@ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" }, + "node_modules/@types/superagent": { + "version": "8.1.7", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.7.tgz", + "integrity": "sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww==", + "dev": true, + "dependencies": { + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*" + } + }, + "node_modules/@types/supertest": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", + "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", + "dev": true, + "dependencies": { + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", @@ -1916,6 +1952,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -1941,6 +1983,12 @@ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, "node_modules/atomic-sleep": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", @@ -2179,6 +2227,27 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2198,6 +2267,12 @@ "node": ">= 0.6" } }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2329,6 +2404,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -2337,6 +2421,16 @@ "node": ">=6" } }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -2392,6 +2486,15 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-abstract": { "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", @@ -3363,6 +3466,12 @@ "node": ">=6" } }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, "node_modules/fast-uri": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.4.0.tgz", @@ -3519,6 +3628,34 @@ "is-callable": "^1.1.3" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz", + "integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==", + "dev": true, + "dependencies": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -3761,6 +3898,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -3840,6 +3983,21 @@ "node": ">= 0.4" } }, + "node_modules/hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, "node_modules/human-signals": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", @@ -3950,6 +4108,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, "node_modules/is-async-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", @@ -4324,6 +4488,12 @@ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, "node_modules/json-schema-ref-resolver": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz", @@ -4489,6 +4659,15 @@ "@jridgewell/sourcemap-codec": "^1.4.15" } }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -4503,6 +4682,15 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromatch": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", @@ -4515,6 +4703,39 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -4602,6 +4823,218 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/npm-run-all/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/npm-run-all/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/npm-run-all/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/npm-run-all/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/npm-run-path": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", @@ -4836,6 +5269,19 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4905,6 +5351,27 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/pino": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/pino/-/pino-9.1.0.tgz", @@ -5111,6 +5578,21 @@ "node": ">=6" } }, + "node_modules/qs": { + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", + "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5140,6 +5622,47 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/readable-stream": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", @@ -5490,6 +6013,15 @@ "node": ">=8" } }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -5550,6 +6082,38 @@ "node": ">=0.10.0" } }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", + "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", + "dev": true + }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", @@ -5615,6 +6179,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.padend": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", + "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/string.prototype.trim": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", @@ -5721,6 +6303,39 @@ "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", "dev": true }, + "node_modules/superagent": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", + "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", + "dev": true, + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^3.5.1", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/supertest": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.0.0.tgz", + "integrity": "sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==", + "dev": true, + "dependencies": { + "methods": "^1.1.2", + "superagent": "^9.0.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6026,6 +6641,16 @@ "punycode": "^2.1.0" } }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "node_modules/vite": { "version": "5.2.13", "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.13.tgz", diff --git a/package.json b/package.json index ff59a39..dd87e67 100644 --- a/package.json +++ b/package.json @@ -37,10 +37,12 @@ "@fakerjs/faker": "^3.0.0", "@types/bcryptjs": "^2.4.6", "@types/node": "^20.14.2", - "npm-run-all": "4.1.5", + "@types/supertest": "^6.0.2", "eslint": "^8.57.0", "eslint-plugin-vitest-globals": "^1.5.0", + "npm-run-all": "4.1.5", "prisma": "^5.15.0", + "supertest": "^7.0.0", "tsx": "^4.15.1", "typescript": "^5.4.5", "vite-tsconfig-paths": "^4.3.2", diff --git a/src/domain/find-a-friend/application/repositories/pets-repository.ts b/src/domain/find-a-friend/application/repositories/pets-repository.ts index 486e591..fa3414c 100644 --- a/src/domain/find-a-friend/application/repositories/pets-repository.ts +++ b/src/domain/find-a-friend/application/repositories/pets-repository.ts @@ -11,7 +11,7 @@ export type PetFilters = { export interface PetsRepository { create(pet: Pet): Promise - findById(id: string, orgId: string): Promise + findById(id: string, orgId?: string): Promise findMany( filters: PetFilters, orgId?: string, diff --git a/src/domain/find-a-friend/application/use-cases/pets-use-cases/fetch-all-adoptable-pet-use-case.spec.ts b/src/domain/find-a-friend/application/use-cases/pets-use-cases/fetch-all-adoptable-pet-use-case.spec.ts index 36c952d..e81f4fd 100644 --- a/src/domain/find-a-friend/application/use-cases/pets-use-cases/fetch-all-adoptable-pet-use-case.spec.ts +++ b/src/domain/find-a-friend/application/use-cases/pets-use-cases/fetch-all-adoptable-pet-use-case.spec.ts @@ -1,3 +1,7 @@ +import UniqueEntityId from '@/core/entities/unique-entity-id' +import { Address } from '@/domain/find-a-friend/enterprise/entities/value-objects/address' +import { PetCharacteristics } from '@/domain/find-a-friend/enterprise/entities/value-objects/pet-characteristics' +import { makePet } from 'tests/factories/make-entities/make-pet' import { MakeFetchAllAdoptablePetUseCase } from 'tests/factories/make-use-cases/make-fetch-all-adoptable-pet-use-case' describe('authenticate org use case', () => { @@ -6,14 +10,69 @@ describe('authenticate org use case', () => { beforeEach(() => { sut = MakeFetchAllAdoptablePetUseCase() }) - it('should be able to authenticate an org', async () => { + it('should be able to fetch orgs', async () => { + for (let i = 1; i <= 25; i++) { + await sut.dependencies.petsRepository.create( + makePet({ + characteristics: new PetCharacteristics({ + isAdoptable: i > 13, + color: 'amarelo', + type: 'Canário', + main: ['Cantante', 'Ativo'], + }), + address: new Address({ + cep: '00777955', + city: 'teste', + neighborhood: 'teste', + number: '123', + state: 'AP', + street: 'teste', + }), + orgId: new UniqueEntityId('789'), + }), + ) + } + const sutResp = await sut.useCase.execute({ filters: { - city: '', + city: 'teste', }, - orgId: '', + orgId: '789', }) expect(sutResp.isRight()).toBeTruthy() }) + + it('should not be able to fetch orgs without filter by city', async () => { + for (let i = 1; i <= 25; i++) { + await sut.dependencies.petsRepository.create( + makePet({ + characteristics: new PetCharacteristics({ + isAdoptable: i > 13, + color: 'amarelo', + type: 'Canário', + main: ['Cantante', 'Ativo'], + }), + address: new Address({ + cep: '00777955', + city: 'teste', + neighborhood: 'teste', + number: '123', + state: 'AP', + street: 'teste', + }), + orgId: new UniqueEntityId('789'), + }), + ) + } + + const sutResp = await sut.useCase.execute({ + filters: { + city: '', + }, + orgId: '789', + }) + + expect(sutResp.value?.pets).toHaveLength(0) + }) }) diff --git a/src/domain/find-a-friend/application/use-cases/pets-use-cases/find-pet-use-case.spec.ts b/src/domain/find-a-friend/application/use-cases/pets-use-cases/find-pet-use-case.spec.ts index 3f624f0..108417b 100644 --- a/src/domain/find-a-friend/application/use-cases/pets-use-cases/find-pet-use-case.spec.ts +++ b/src/domain/find-a-friend/application/use-cases/pets-use-cases/find-pet-use-case.spec.ts @@ -60,7 +60,6 @@ describe('find pet use case', () => { ) const sutResp = await sut.useCase.execute({ - orgId: orgs[0].id.value, petId: pets[0].id.value, }) diff --git a/src/domain/find-a-friend/application/use-cases/pets-use-cases/find-pet-use-case.ts b/src/domain/find-a-friend/application/use-cases/pets-use-cases/find-pet-use-case.ts index 0b96b53..b6cbdf6 100644 --- a/src/domain/find-a-friend/application/use-cases/pets-use-cases/find-pet-use-case.ts +++ b/src/domain/find-a-friend/application/use-cases/pets-use-cases/find-pet-use-case.ts @@ -4,7 +4,6 @@ import { Pet } from '../../../enterprise/entities/pet' import { ResourceNotFoundError } from '@/core/errors/errors/resource-not-found-error' export interface FindPetUseCaseRequest { - orgId: string petId: string } @@ -14,10 +13,9 @@ export class FindPetUseCase { constructor(private petsRepository: PetsRepository) {} async execute({ - orgId, petId, }: FindPetUseCaseRequest): Promise { - const pet = await this.petsRepository.findById(petId, orgId) + const pet = await this.petsRepository.findById(petId) if (!pet) return left(new ResourceNotFoundError()) diff --git a/src/domain/find-a-friend/application/use-cases/pets-use-cases/want-to-adopt-use-case.spec.ts b/src/domain/find-a-friend/application/use-cases/pets-use-cases/want-to-adopt-use-case.spec.ts index ddcee74..5074223 100644 --- a/src/domain/find-a-friend/application/use-cases/pets-use-cases/want-to-adopt-use-case.spec.ts +++ b/src/domain/find-a-friend/application/use-cases/pets-use-cases/want-to-adopt-use-case.spec.ts @@ -62,7 +62,6 @@ describe('want to adopt use case', () => { ) const sutResp = await sut.useCase.execute({ - orgId: orgs[0].id.value, petId: pets[0].id.value, }) diff --git a/src/domain/find-a-friend/application/use-cases/pets-use-cases/want-to-adopt-use-case.ts b/src/domain/find-a-friend/application/use-cases/pets-use-cases/want-to-adopt-use-case.ts index 78a6801..764ee4a 100644 --- a/src/domain/find-a-friend/application/use-cases/pets-use-cases/want-to-adopt-use-case.ts +++ b/src/domain/find-a-friend/application/use-cases/pets-use-cases/want-to-adopt-use-case.ts @@ -5,7 +5,6 @@ import { OrgsRepository } from '../../repositories/orgs-repository' import { UnauthorizedError } from '@/core/errors/errors/unauthorized-error' export interface WhantToAdoptUseCaseRequest { - orgId: string petId: string } @@ -21,14 +20,13 @@ export class WhantToAdoptUseCase { ) {} async execute({ - orgId, petId, }: WhantToAdoptUseCaseRequest): Promise { - const pet = await this.petsRepository.findById(petId, orgId) + const pet = await this.petsRepository.findById(petId) if (!pet) return left(new ResourceNotFoundError()) if (!pet.characteristics.isAdoptable) return left(new UnauthorizedError()) - const org = await this.orgsRepository.findById(orgId) + const org = await this.orgsRepository.findById(pet.orgId.value) if (!org) return left(new ResourceNotFoundError()) const whatsapp = org.whatsapp.format diff --git a/src/env/env.ts b/src/env/env.ts index 967f038..48ff96d 100644 --- a/src/env/env.ts +++ b/src/env/env.ts @@ -8,6 +8,7 @@ const envSchema = z.object({ 'postgresql://postgres:docker@localhost:5432/daily-diet?schema=public', ), PORT: z.string().optional().default('3000').pipe(z.coerce.number()), + NODE_ENV: z.enum(['dev', 'test', 'prod']).default('prod'), }) const _env = envSchema.safeParse(process.env) diff --git a/src/infra/auth/cryptography/fastify-jwt-encoder.ts b/src/infra/auth/cryptography/fastify-jwt-encoder.ts index 9a6e9a8..eda787f 100644 --- a/src/infra/auth/cryptography/fastify-jwt-encoder.ts +++ b/src/infra/auth/cryptography/fastify-jwt-encoder.ts @@ -1,4 +1,4 @@ -import { Encoder } from '@/domain/application/cryptography/encoder' +import { Encoder } from '@/domain/find-a-friend/application/cryptography/encoder' import { FastifyReply } from 'fastify' export class FastifyJwtEncoder implements Encoder { diff --git a/src/infra/database/prisma.ts b/src/infra/database/prisma.ts index 95f0b6c..b5f1e41 100644 --- a/src/infra/database/prisma.ts +++ b/src/infra/database/prisma.ts @@ -1,5 +1,6 @@ +import { env } from '@/env/env' import { PrismaClient } from '@prisma/client' export const prisma = new PrismaClient({ - log: ['query', 'error', 'warn'], + log: env.NODE_ENV === 'dev' ? ['query', 'error', 'warn'] : ['error'], }) diff --git a/src/infra/database/reposities/prisma-pet-repository.ts b/src/infra/database/reposities/prisma-pet-repository.ts index 6694b32..20349f9 100644 --- a/src/infra/database/reposities/prisma-pet-repository.ts +++ b/src/infra/database/reposities/prisma-pet-repository.ts @@ -22,11 +22,15 @@ export class PrismaPetsRepository implements PetsRepository { return mappedPet } - async findById(id: string, orgId: string): Promise { + async findById(id: string, orgId?: string): Promise { const PrismaPet = await prisma.pet.findUnique({ where: { id, - orgId, + AND: [ + { + orgId, + }, + ], }, }) diff --git a/src/infra/http/controllers/orgs-controllers/authenticate-org-controllers.e2e-spec.ts b/src/infra/http/controllers/orgs-controllers/authenticate-org-controllers.e2e-spec.ts new file mode 100644 index 0000000..f05178c --- /dev/null +++ b/src/infra/http/controllers/orgs-controllers/authenticate-org-controllers.e2e-spec.ts @@ -0,0 +1,44 @@ +import { app } from '@/infra/app' +import { prisma } from '@/infra/database/prisma' +import request from 'supertest' + +describe('authenticate org controller', () => { + beforeAll(async () => { + await app.ready() + }) + + afterAll(async () => { + await app.close() + }) + + it('should be able to authenticate org', async () => { + const createOrgRespResp = await request(app.server) + .post('/orgs') + .send({ + name: 'bruno', + email: 'bruno@gmail.com', + password: '123', + address: { + cep: '00444999', + number: '987', + street: 'reua teste', + neighborhood: 'meu bairro', + city: 'the daily planet', + state: 'SP', + }, + whatsapp: '11933337788', + }) + + const sutResp = await request(app.server).post('/sessions').send({ + email: 'bruno@gmail.com', + password: '123', + }) + + const orgs = await prisma.org.findMany() + + expect(createOrgRespResp.statusCode).toEqual(201) + expect(sutResp.statusCode).toEqual(200) + expect(sutResp.body.token).toEqual(expect.any(String)) + expect(orgs).toHaveLength(1) + }) +}) diff --git a/src/infra/http/controllers/orgs-controllers/register-org-controllers.e2e-spec.ts b/src/infra/http/controllers/orgs-controllers/register-org-controllers.e2e-spec.ts new file mode 100644 index 0000000..664b26a --- /dev/null +++ b/src/infra/http/controllers/orgs-controllers/register-org-controllers.e2e-spec.ts @@ -0,0 +1,37 @@ +import { app } from '@/infra/app' +import { prisma } from '@/infra/database/prisma' +import request from 'supertest' + +describe('register org controller', () => { + beforeAll(async () => { + await app.ready() + }) + + afterAll(async () => { + await app.close() + }) + + it('should be able to register a new org', async () => { + const sutResp = await request(app.server) + .post('/orgs') + .send({ + name: 'bruno', + email: 'bruno@gmail.com', + password: '123', + address: { + cep: '00444999', + number: '987', + street: 'reua teste', + neighborhood: 'meu bairro', + city: 'the daily planet', + state: 'SP', + }, + whatsapp: '11933337788', + }) + + const orgs = await prisma.org.findMany() + + expect(sutResp.statusCode).toEqual(201) + expect(orgs).toHaveLength(1) + }) +}) diff --git a/src/infra/http/controllers/pets-controllers/fetch-all-adoptable-pets-controller.e2e-spec.ts b/src/infra/http/controllers/pets-controllers/fetch-all-adoptable-pets-controller.e2e-spec.ts new file mode 100644 index 0000000..f70a8f9 --- /dev/null +++ b/src/infra/http/controllers/pets-controllers/fetch-all-adoptable-pets-controller.e2e-spec.ts @@ -0,0 +1,103 @@ +import { PetCharacteristics } from '@/domain/find-a-friend/enterprise/entities/value-objects/pet-characteristics' +import { app } from '@/infra/app' +import { prisma } from '@/infra/database/prisma' +import request from 'supertest' + +describe('fetch all adoptable pets controller', () => { + beforeAll(async () => { + await app.ready() + }) + + afterAll(async () => { + await app.close() + }) + + it('should be able to fetch all adoptable pets with filters', async () => { + const createOrgRespResp = await request(app.server) + .post('/orgs') + .send({ + name: 'bruno', + email: 'bruno@gmail.com', + password: '123', + address: { + cep: '00444999', + number: '987', + street: 'reua teste', + neighborhood: 'meu bairro', + city: 'the daily planet', + state: 'SP', + }, + whatsapp: '11933337788', + }) + + const authOrgResp = await request(app.server).post('/sessions').send({ + email: 'bruno@gmail.com', + password: '123', + }) + + const token = authOrgResp.body.token + const orgs = await prisma.org.findMany() + const orgId = orgs[0].id + + type Charachteristics = { + main?: PetCharacteristics['main'] + type?: PetCharacteristics['type'] + color?: PetCharacteristics['color'] + isAdoptable: boolean + } + + await request(app.server) + .post('/pets') + .set('Authorization', `Bearer ${token}`) + .send({ + orgId, + name: 'cat', + petCharacteristics: { + main: ['diurno', 'Inteligente', 'ativo'], + color: 'preto', + type: 'Gato', + isAdoptable: true, + }, + }) + + await request(app.server) + .post('/pets') + .set('Authorization', `Bearer ${token}`) + .send({ + orgId, + name: 'oi', + petCharacteristics: { + main: ['Independente', 'limpo', 'Leal'], + color: 'preto', + type: 'Coelho', + isAdoptable: true, + }, + }) + + await request(app.server) + .post('/pets') + .set('Authorization', `Bearer ${token}`) + .send({ + orgId, + name: 'oi', + petCharacteristics: { + main: ['Aquático', 'Pequeno', 'Ativo', 'requer ambiente específico'], + color: 'preto', + type: 'Peixe', + isAdoptable: true, + }, + }) + + const sutResp = await request(app.server) + .get( + '/pets?city=the daily planet&mainCharacteristics=diurno,Ativo&color=preto', + ) + .send() + + expect(createOrgRespResp.statusCode).toEqual(201) + expect(authOrgResp.statusCode).toEqual(200) + expect(sutResp.statusCode).toEqual(200) + expect(sutResp.body.pets).toHaveLength(2) + expect(orgs).toHaveLength(1) + }) +}) diff --git a/src/infra/http/controllers/pets-controllers/find-pet-controller.e2e-spec.ts b/src/infra/http/controllers/pets-controllers/find-pet-controller.e2e-spec.ts new file mode 100644 index 0000000..25ac89d --- /dev/null +++ b/src/infra/http/controllers/pets-controllers/find-pet-controller.e2e-spec.ts @@ -0,0 +1,109 @@ +import { PetCharacteristics } from '@/domain/find-a-friend/enterprise/entities/value-objects/pet-characteristics' +import { app } from '@/infra/app' +import { prisma } from '@/infra/database/prisma' +import request from 'supertest' + +describe('find pet controller', () => { + beforeAll(async () => { + await app.ready() + }) + + afterAll(async () => { + await app.close() + }) + + it('should be able to find a pet by id', async () => { + const createOrgRespResp = await request(app.server) + .post('/orgs') + .send({ + name: 'bruno', + email: 'bruno@gmail.com', + password: '123', + address: { + cep: '00444999', + number: '987', + street: 'reua teste', + neighborhood: 'meu bairro', + city: 'the daily planet', + state: 'SP', + }, + whatsapp: '11933337788', + }) + + const authOrgResp = await request(app.server).post('/sessions').send({ + email: 'bruno@gmail.com', + password: '123', + }) + + const token = authOrgResp.body.token + const orgs = await prisma.org.findMany() + const orgId = orgs[0].id + + type Charachteristics = { + main?: PetCharacteristics['main'] + type?: PetCharacteristics['type'] + color?: PetCharacteristics['color'] + isAdoptable: boolean + } + + await request(app.server) + .post('/pets') + .set('Authorization', `Bearer ${token}`) + .send({ + orgId, + name: 'cat', + petCharacteristics: { + main: ['diurno', 'Inteligente', 'ativo'], + color: 'preto', + type: 'Gato', + isAdoptable: true, + }, + }) + + await request(app.server) + .post('/pets') + .set('Authorization', `Bearer ${token}`) + .send({ + orgId, + name: 'oi', + petCharacteristics: { + main: ['Independente', 'limpo', 'Leal'], + color: 'preto', + type: 'Coelho', + isAdoptable: true, + }, + }) + + await request(app.server) + .post('/pets') + .set('Authorization', `Bearer ${token}`) + .send({ + orgId, + name: 'oi', + petCharacteristics: { + main: ['Aquático', 'Pequeno', 'Ativo', 'requer ambiente específico'], + color: 'preto', + type: 'Peixe', + isAdoptable: true, + }, + }) + + const pets = await prisma.pet.findMany({ where: { type: 'Peixe' } }) + + const petId = pets[0].id + + const sutResp = await request(app.server).get(`/pets/${petId}`).send() + + expect(createOrgRespResp.statusCode).toEqual(201) + expect(authOrgResp.statusCode).toEqual(200) + expect(sutResp.statusCode).toEqual(200) + expect(sutResp.body.pet).toEqual( + expect.objectContaining({ + details: ['Aquático', 'Pequeno', 'Ativo', 'requer ambiente específico'], + color: 'preto', + type: 'Peixe', + }), + ) + expect(orgs).toHaveLength(1) + }) +}) diff --git a/src/infra/http/controllers/pets-controllers/find-pet-controller.ts b/src/infra/http/controllers/pets-controllers/find-pet-controller.ts index c6418ae..0301f03 100644 --- a/src/infra/http/controllers/pets-controllers/find-pet-controller.ts +++ b/src/infra/http/controllers/pets-controllers/find-pet-controller.ts @@ -3,21 +3,22 @@ import { FindPetUseCase } from '@/domain/find-a-friend/application/use-cases/pet import { PrismaPetsRepository } from '@/infra/database/reposities/prisma-pet-repository' import { FastifyReply, FastifyRequest } from 'fastify' import z from 'zod' +import { PetPresenter } from '../../presenters/pet-presenter' export async function findPetController( req: FastifyRequest, res: FastifyReply, ) { const paramsSchema = z.object({ - petId: z.string(), + id: z.string(), }) - const params = paramsSchema.parse(req.params) + const { id: petId } = paramsSchema.parse(req.params) const petsRepository = new PrismaPetsRepository() const useCase = new FindPetUseCase(petsRepository) - const resp = await useCase.execute({ ...params, orgId: req.user.sub }) + const resp = await useCase.execute({ petId }) if (resp.isLeft()) { const error = resp.value @@ -29,7 +30,7 @@ export async function findPetController( if (resp.isRight()) { const { pet } = resp.value - res.status(200).send({ pet }) + res.status(200).send({ pet: PetPresenter.basic(pet) }) } res.status(500).send({ message: 'Internal server error.' }) diff --git a/src/infra/http/controllers/pets-controllers/register-pet-controller.e2e-spec.ts b/src/infra/http/controllers/pets-controllers/register-pet-controller.e2e-spec.ts new file mode 100644 index 0000000..aa44127 --- /dev/null +++ b/src/infra/http/controllers/pets-controllers/register-pet-controller.e2e-spec.ts @@ -0,0 +1,60 @@ +import { app } from '@/infra/app' +import { prisma } from '@/infra/database/prisma' +import request from 'supertest' + +describe('register pet controller', () => { + beforeAll(async () => { + await app.ready() + }) + + afterAll(async () => { + await app.close() + }) + + it('should be able to register a pet', async () => { + const createOrgRespResp = await request(app.server) + .post('/orgs') + .send({ + name: 'bruno', + email: 'bruno@gmail.com', + password: '123', + address: { + cep: '00444999', + number: '987', + street: 'reua teste', + neighborhood: 'meu bairro', + city: 'the daily planet', + state: 'SP', + }, + whatsapp: '11933337788', + }) + + const authOrgResp = await request(app.server).post('/sessions').send({ + email: 'bruno@gmail.com', + password: '123', + }) + + const token = authOrgResp.body.token + const orgs = await prisma.org.findMany() + const orgId = orgs[0].id + + const sutResp = await request(app.server) + .post('/pets') + .set('Authorization', `Bearer ${token}`) + .send({ + orgId, + name: 'cat', + petCharacteristics: { + main: ['diurno', 'Inteligente', 'ativo'], + color: 'preto', + type: 'Gato', + isAdoptable: true, + }, + }) + + expect(createOrgRespResp.statusCode).toEqual(201) + expect(authOrgResp.statusCode).toEqual(200) + expect(sutResp.statusCode).toEqual(201) + expect(orgs).toHaveLength(1) + }) +}) diff --git a/src/infra/http/controllers/pets-controllers/want-to-adopt-controller.e2e-spec.ts b/src/infra/http/controllers/pets-controllers/want-to-adopt-controller.e2e-spec.ts new file mode 100644 index 0000000..03ac34b --- /dev/null +++ b/src/infra/http/controllers/pets-controllers/want-to-adopt-controller.e2e-spec.ts @@ -0,0 +1,104 @@ +import { PetCharacteristics } from '@/domain/find-a-friend/enterprise/entities/value-objects/pet-characteristics' +import { Whatsapp } from '@/domain/find-a-friend/enterprise/entities/value-objects/whatsapp' +import { app } from '@/infra/app' +import { prisma } from '@/infra/database/prisma' +import request from 'supertest' + +describe('want to adopt controller', () => { + beforeAll(async () => { + await app.ready() + }) + + afterAll(async () => { + await app.close() + }) + + it('should be able to send the respective org whatsapp when a user wants to adopt a pet', async () => { + const createOrgRespResp = await request(app.server) + .post('/orgs') + .send({ + name: 'bruno', + email: 'bruno@gmail.com', + password: '123', + address: { + cep: '00444999', + number: '987', + street: 'reua teste', + neighborhood: 'meu bairro', + city: 'the daily planet', + state: 'SP', + }, + whatsapp: '11933337788', + }) + + const authOrgResp = await request(app.server).post('/sessions').send({ + email: 'bruno@gmail.com', + password: '123', + }) + + const token = authOrgResp.body.token + const orgs = await prisma.org.findMany() + const orgId = orgs[0].id + + type Charachteristics = { + main?: PetCharacteristics['main'] + type?: PetCharacteristics['type'] + color?: PetCharacteristics['color'] + isAdoptable: boolean + } + + await request(app.server) + .post('/pets') + .set('Authorization', `Bearer ${token}`) + .send({ + orgId, + name: 'cat', + petCharacteristics: { + main: ['diurno', 'Inteligente', 'ativo'], + color: 'preto', + type: 'Gato', + isAdoptable: true, + }, + }) + + await request(app.server) + .post('/pets') + .set('Authorization', `Bearer ${token}`) + .send({ + orgId, + name: 'oi', + petCharacteristics: { + main: ['Independente', 'limpo', 'Leal'], + color: 'preto', + type: 'Coelho', + isAdoptable: true, + }, + }) + + await request(app.server) + .post('/pets') + .set('Authorization', `Bearer ${token}`) + .send({ + orgId, + name: 'oi', + petCharacteristics: { + main: ['Aquático', 'Pequeno', 'Ativo', 'requer ambiente específico'], + color: 'preto', + type: 'Peixe', + isAdoptable: true, + }, + }) + + const pets = await prisma.pet.findMany({ where: { type: 'Peixe' } }) + + const petId = pets[0].id + + const sutResp = await request(app.server).get(`/pets/adopt/${petId}`).send() + + expect(createOrgRespResp.statusCode).toEqual(201) + expect(authOrgResp.statusCode).toEqual(200) + expect(sutResp.statusCode).toEqual(200) + expect(sutResp.body.whatsapp).toEqual(new Whatsapp('11933337788').format) + expect(orgs).toHaveLength(1) + }) +}) diff --git a/src/infra/http/controllers/pets-controllers/want-to-adopt-controller.ts b/src/infra/http/controllers/pets-controllers/want-to-adopt-controller.ts index 61b853e..703ec58 100644 --- a/src/infra/http/controllers/pets-controllers/want-to-adopt-controller.ts +++ b/src/infra/http/controllers/pets-controllers/want-to-adopt-controller.ts @@ -9,22 +9,17 @@ export async function wantToAdoptController( req: FastifyRequest, res: FastifyReply, ) { - const bodySchema = z.object({ - orgId: z.string().uuid(), - }) - const paramsSchema = z.object({ - petId: z.string(), + id: z.string(), }) - const params = paramsSchema.parse(req.params) - const body = bodySchema.parse(req.body) + const { id: petId } = paramsSchema.parse(req.params) const petsRepository = new PrismaPetsRepository() const orgsRepository = new PrismaOrgsRepository() const useCase = new WhantToAdoptUseCase(petsRepository, orgsRepository) - const resp = await useCase.execute({ ...body, ...params }) + const resp = await useCase.execute({ petId }) if (resp.isLeft()) { const error = resp.value diff --git a/src/infra/http/middlewares/jwt-verify.ts b/src/infra/http/middlewares/jwt-verify.ts new file mode 100644 index 0000000..bdfb4c6 --- /dev/null +++ b/src/infra/http/middlewares/jwt-verify.ts @@ -0,0 +1,5 @@ +import { FastifyReply, FastifyRequest } from 'fastify' + +export async function jwtVerify(req: FastifyRequest, res: FastifyReply) { // eslint-disable-line + await req.jwtVerify() +} diff --git a/src/infra/http/routes/pet-routes.ts b/src/infra/http/routes/pet-routes.ts index 162c3fe..d0c8255 100644 --- a/src/infra/http/routes/pet-routes.ts +++ b/src/infra/http/routes/pet-routes.ts @@ -3,9 +3,10 @@ import { fetchAllAdoptablePetsController } from '../controllers/pets-controllers import { registerPetController } from '../controllers/pets-controllers/register-pet-controller' import { wantToAdoptController } from '../controllers/pets-controllers/want-to-adopt-controller' import { findPetController } from '../controllers/pets-controllers/find-pet-controller' +import { jwtVerify } from '../middlewares/jwt-verify' export async function petRoutes(app: FastifyInstance) { - app.post('/', registerPetController) + app.post('/', { onRequest: [jwtVerify] }, registerPetController) app.get('/', fetchAllAdoptablePetsController) app.get('/:id', findPetController) app.get('/adopt/:id', wantToAdoptController) diff --git a/tests/factories/make-entities/make-pet.ts b/tests/factories/make-entities/make-pet.ts index 63d18d8..4893663 100644 --- a/tests/factories/make-entities/make-pet.ts +++ b/tests/factories/make-entities/make-pet.ts @@ -39,7 +39,7 @@ export function makePet(override?: Partial) { cep: faker.number.int({ min: 10000000, max: 99999999 }).toString(), city: faker.location.city(), neighborhood: faker.lorem.sentence(2), - number: faker.number.int({ min: 0, max: 10000 }), + number: String(faker.number.int({ min: 0, max: 10000 })), state: states[Math.floor(Math.random() * states.length)], street: faker.location.street(), }) diff --git a/tests/repositories/in-memory-pets-repository.ts b/tests/repositories/in-memory-pets-repository.ts index 5f64760..7d78efe 100644 --- a/tests/repositories/in-memory-pets-repository.ts +++ b/tests/repositories/in-memory-pets-repository.ts @@ -14,10 +14,10 @@ export class InMemoryPetsRepository implements PetsRepository { return org } - async findById(id: string, orgId: string): Promise { + async findById(id: string, orgId?: string): Promise { return ( - this.items.find( - (item) => item.id.value === id && item.orgId.value === orgId, + this.items.find((item) => + item.id.value === id && orgId ? item.orgId.value === orgId : true, ) ?? null ) }