From 98d4ffb89012c1684f3eb64618a58885ad84878b Mon Sep 17 00:00:00 2001 From: Marcelo Wiebbelling Date: Wed, 1 Oct 2025 17:20:53 +0200 Subject: [PATCH 1/5] Nuxt 4 upgrade --- nuxt.config.ts | 4 ++++ package.json | 2 +- pnpm-lock.yaml | 60 ++++++++++++++------------------------------------ 3 files changed, 21 insertions(+), 45 deletions(-) diff --git a/nuxt.config.ts b/nuxt.config.ts index 6a94b18..4618d49 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -59,6 +59,10 @@ export default defineNuxtConfig({ transpile: ['vuetify'], }, + future: { + compatibilityVersion: 4, + }, + modules: [ '@pinia/nuxt', 'nuxt-schema-org', diff --git a/package.json b/package.json index 6a021da..81fc25b 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "@nuxt/test-utils": "^3.19.2", "@vitejs/plugin-vue": "^6.0.1", "jsdom": "^26.1.0", - "nuxt": "^3.19.2", + "nuxt": "^4.1.2", "vite-plugin-vuetify": "^2.1.2", "vitest": "^3.2.4", "vuetify": "^3.10.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a95226b..2f49872 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,8 +34,8 @@ importers: specifier: ^26.1.0 version: 26.1.0 nuxt: - specifier: ^3.19.2 - version: 3.19.2(@netlify/blobs@9.1.1)(@parcel/watcher@2.5.1)(@types/node@22.13.10)(@vue/compiler-sfc@3.5.22)(db0@0.3.2)(ioredis@5.8.0)(magicast@0.3.5)(rollup@4.52.3)(terser@5.44.0)(typescript@5.8.2)(vite@7.1.7(@types/node@22.13.10)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1) + specifier: ^4.1.2 + version: 4.1.2(@netlify/blobs@9.1.1)(@parcel/watcher@2.5.1)(@types/node@22.13.10)(@vue/compiler-sfc@3.5.22)(db0@0.3.2)(ioredis@5.8.0)(magicast@0.3.5)(rollup@4.52.3)(terser@5.44.0)(typescript@5.8.2)(vite@7.1.7(@types/node@22.13.10)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1) vite-plugin-vuetify: specifier: ^2.1.2 version: 2.1.2(vite@7.1.7(@types/node@22.13.10)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.2))(vuetify@3.10.4) @@ -474,8 +474,8 @@ packages: resolution: {integrity: sha512-P5q41xeEOa6ZQC0PvIP7TSBmOAMxXK4qihDcCbYIJq8RcVsEPbGZVlidmxE6EOw1ucSyodq9nbV31FAKwoL4NQ==} engines: {node: '>=18.12.0'} - '@nuxt/schema@3.19.2': - resolution: {integrity: sha512-kMN2oIfrsMc8ACrRweYRG7Q44/KuHG5y7L+4szQhfOgN78OiYkxiM/nSsLH0K2bJq8Eavg+WGfgACj4Lsy+YqQ==} + '@nuxt/schema@4.1.2': + resolution: {integrity: sha512-uFr13C6c52OFbF3hZVIV65KvhQRyrwp1GlAm7EVNGjebY8279QEel57T4R9UA1dn2Et6CBynBFhWoFwwo97Pig==} engines: {node: ^14.18.0 || >=16.10.0} '@nuxt/telemetry@2.6.6': @@ -519,8 +519,8 @@ packages: vitest: optional: true - '@nuxt/vite-builder@3.19.2': - resolution: {integrity: sha512-SESdHAKWy63RKG3uqrBEJvTbfkmEsiggmDEqjEwhBP2fe0E6bGTmLpX/Eh4AuOLbZuZOmir984OHFiM/Q/MLhg==} + '@nuxt/vite-builder@4.1.2': + resolution: {integrity: sha512-to9NKVtzMBtyuhIIVgwo/ph5UCONcxkVsoAjm8HnSkDi0o9nDPhHOAg1AUMlvPnHpdXOzwnSrXo/t8E7W+UZ/A==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: vue: ^3.3.4 @@ -1801,10 +1801,6 @@ packages: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} - enhanced-resolve@5.18.3: - resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} - engines: {node: '>=10.13.0'} - entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -1890,9 +1886,6 @@ packages: exsolve@1.0.7: resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==} - externality@1.0.2: - resolution: {integrity: sha512-LyExtJWKxtgVzmgtEHyQtLFpw1KFhQphF9nTG8TpAIVkiI/xQ3FJh75tRFLYl4hkn7BNIIdLJInuDAavX35pMw==} - fake-indexeddb@6.2.2: resolution: {integrity: sha512-SGbf7fzjeHz3+12NO1dYigcYn4ivviaeULV5yY5rdGihBvvgwMds4r4UBbNIUMwkze57KTDm32rq3j1Az8mzEw==} engines: {node: '>=18'} @@ -2513,13 +2506,13 @@ packages: peerDependencies: h3: ^1 - nuxt@3.19.2: - resolution: {integrity: sha512-z4ouGRMOWqZ1xaZ+HdRBRVlZcKSoDBpRxQ30GJ2dllraZMC/gNpTGuY32H3xP5b4R29b8uYcK+B8LFQoRHpO8A==} + nuxt@4.1.2: + resolution: {integrity: sha512-g5mwszCZT4ZeGJm83nxoZvtvZoAEaY65VDdn7p7UgznePbRaEJJ1KS1OIld4FPVkoDZ8TEVuDNqI9gUn12Exvg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@parcel/watcher': ^2.1.0 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@types/node': '>=18.12.0' peerDependenciesMeta: '@parcel/watcher': optional: true @@ -3187,10 +3180,6 @@ packages: resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} engines: {node: '>=18'} - tapable@2.2.3: - resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==} - engines: {node: '>=6'} - tar-stream@3.1.7: resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} @@ -4285,7 +4274,7 @@ snapshots: transitivePeerDependencies: - magicast - '@nuxt/schema@3.19.2': + '@nuxt/schema@4.1.2': dependencies: '@vue/shared': 3.5.22 consola: 3.4.2 @@ -4345,9 +4334,9 @@ snapshots: - magicast - typescript - '@nuxt/vite-builder@3.19.2(@types/node@22.13.10)(magicast@0.3.5)(rollup@4.52.3)(terser@5.44.0)(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2))(yaml@2.8.1)': + '@nuxt/vite-builder@4.1.2(@types/node@22.13.10)(magicast@0.3.5)(rollup@4.52.3)(terser@5.44.0)(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2))(yaml@2.8.1)': dependencies: - '@nuxt/kit': 3.19.2(magicast@0.3.5) + '@nuxt/kit': 4.1.2(magicast@0.3.5) '@rollup/plugin-replace': 6.0.2(rollup@4.52.3) '@vitejs/plugin-vue': 6.0.1(vite@7.1.7(@types/node@22.13.10)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.2)) '@vitejs/plugin-vue-jsx': 5.1.1(vite@7.1.7(@types/node@22.13.10)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.2)) @@ -4358,7 +4347,6 @@ snapshots: esbuild: 0.25.10 escape-string-regexp: 5.0.0 exsolve: 1.0.7 - externality: 1.0.2 get-port-please: 3.2.0 h3: 1.15.4 jiti: 2.6.1 @@ -4366,9 +4354,7 @@ snapshots: magic-string: 0.30.19 mlly: 1.8.0 mocked-exports: 0.1.1 - ohash: 2.0.11 pathe: 2.0.3 - perfect-debounce: 2.0.0 pkg-types: 2.3.0 postcss: 8.5.6 rollup-plugin-visualizer: 6.0.3(rollup@4.52.3) @@ -5538,11 +5524,6 @@ snapshots: encodeurl@2.0.0: {} - enhanced-resolve@5.18.3: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.3 - entities@4.5.0: {} entities@6.0.1: {} @@ -5638,13 +5619,6 @@ snapshots: exsolve@1.0.7: {} - externality@1.0.2: - dependencies: - enhanced-resolve: 5.18.3 - mlly: 1.8.0 - pathe: 1.1.2 - ufo: 1.6.1 - fake-indexeddb@6.2.2: {} fast-fifo@1.3.2: {} @@ -6375,15 +6349,15 @@ snapshots: - magicast - vue - nuxt@3.19.2(@netlify/blobs@9.1.1)(@parcel/watcher@2.5.1)(@types/node@22.13.10)(@vue/compiler-sfc@3.5.22)(db0@0.3.2)(ioredis@5.8.0)(magicast@0.3.5)(rollup@4.52.3)(terser@5.44.0)(typescript@5.8.2)(vite@7.1.7(@types/node@22.13.10)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1): + nuxt@4.1.2(@netlify/blobs@9.1.1)(@parcel/watcher@2.5.1)(@types/node@22.13.10)(@vue/compiler-sfc@3.5.22)(db0@0.3.2)(ioredis@5.8.0)(magicast@0.3.5)(rollup@4.52.3)(terser@5.44.0)(typescript@5.8.2)(vite@7.1.7(@types/node@22.13.10)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1): dependencies: '@nuxt/cli': 3.28.0(magicast@0.3.5) '@nuxt/devalue': 2.0.2 '@nuxt/devtools': 2.6.5(vite@7.1.7(@types/node@22.13.10)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.8.2)) - '@nuxt/kit': 3.19.2(magicast@0.3.5) - '@nuxt/schema': 3.19.2 + '@nuxt/kit': 4.1.2(magicast@0.3.5) + '@nuxt/schema': 4.1.2 '@nuxt/telemetry': 2.6.6(magicast@0.3.5) - '@nuxt/vite-builder': 3.19.2(@types/node@22.13.10)(magicast@0.3.5)(rollup@4.52.3)(terser@5.44.0)(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2))(yaml@2.8.1) + '@nuxt/vite-builder': 4.1.2(@types/node@22.13.10)(magicast@0.3.5)(rollup@4.52.3)(terser@5.44.0)(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2))(yaml@2.8.1) '@unhead/vue': 2.0.17(vue@3.5.22(typescript@5.8.2)) '@vue/shared': 3.5.22 c12: 3.3.0(magicast@0.3.5) @@ -7206,8 +7180,6 @@ snapshots: system-architecture@0.1.0: {} - tapable@2.2.3: {} - tar-stream@3.1.7: dependencies: b4a: 1.7.3 From 2133b91699f94345883b32d73ee890be50bd0da1 Mon Sep 17 00:00:00 2001 From: Marcelo Wiebbelling Date: Wed, 1 Oct 2025 17:21:37 +0200 Subject: [PATCH 2/5] New directory structure --- {assets => app/assets}/indicadores.json | 0 {components => app/components}/InvestmentInput.vue | 0 {components => app/components}/InvestmentResult.vue | 0 {components => app/components}/InvestmentSimulation.vue | 0 {components => app/components}/NavigationBar.vue | 0 {components => app/components}/investment/AmountInput.vue | 0 {components => app/components}/investment/IndexCdbInput.vue | 0 {components => app/components}/investment/IndexDiInput.vue | 0 {components => app/components}/investment/IndexLcxInput.vue | 0 {components => app/components}/investment/IndexSelicInput.vue | 0 {components => app/components}/investment/PeriodInput.vue | 0 {components => app/components}/investment/PeriodTypeInput.vue | 0 {layouts => app/layouts}/default.vue | 0 {pages => app/pages}/index.vue | 0 {pages => app/pages}/sobre.vue | 0 {plugins => app/plugins}/vuetify.js | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename {assets => app/assets}/indicadores.json (100%) rename {components => app/components}/InvestmentInput.vue (100%) rename {components => app/components}/InvestmentResult.vue (100%) rename {components => app/components}/InvestmentSimulation.vue (100%) rename {components => app/components}/NavigationBar.vue (100%) rename {components => app/components}/investment/AmountInput.vue (100%) rename {components => app/components}/investment/IndexCdbInput.vue (100%) rename {components => app/components}/investment/IndexDiInput.vue (100%) rename {components => app/components}/investment/IndexLcxInput.vue (100%) rename {components => app/components}/investment/IndexSelicInput.vue (100%) rename {components => app/components}/investment/PeriodInput.vue (100%) rename {components => app/components}/investment/PeriodTypeInput.vue (100%) rename {layouts => app/layouts}/default.vue (100%) rename {pages => app/pages}/index.vue (100%) rename {pages => app/pages}/sobre.vue (100%) rename {plugins => app/plugins}/vuetify.js (100%) diff --git a/assets/indicadores.json b/app/assets/indicadores.json similarity index 100% rename from assets/indicadores.json rename to app/assets/indicadores.json diff --git a/components/InvestmentInput.vue b/app/components/InvestmentInput.vue similarity index 100% rename from components/InvestmentInput.vue rename to app/components/InvestmentInput.vue diff --git a/components/InvestmentResult.vue b/app/components/InvestmentResult.vue similarity index 100% rename from components/InvestmentResult.vue rename to app/components/InvestmentResult.vue diff --git a/components/InvestmentSimulation.vue b/app/components/InvestmentSimulation.vue similarity index 100% rename from components/InvestmentSimulation.vue rename to app/components/InvestmentSimulation.vue diff --git a/components/NavigationBar.vue b/app/components/NavigationBar.vue similarity index 100% rename from components/NavigationBar.vue rename to app/components/NavigationBar.vue diff --git a/components/investment/AmountInput.vue b/app/components/investment/AmountInput.vue similarity index 100% rename from components/investment/AmountInput.vue rename to app/components/investment/AmountInput.vue diff --git a/components/investment/IndexCdbInput.vue b/app/components/investment/IndexCdbInput.vue similarity index 100% rename from components/investment/IndexCdbInput.vue rename to app/components/investment/IndexCdbInput.vue diff --git a/components/investment/IndexDiInput.vue b/app/components/investment/IndexDiInput.vue similarity index 100% rename from components/investment/IndexDiInput.vue rename to app/components/investment/IndexDiInput.vue diff --git a/components/investment/IndexLcxInput.vue b/app/components/investment/IndexLcxInput.vue similarity index 100% rename from components/investment/IndexLcxInput.vue rename to app/components/investment/IndexLcxInput.vue diff --git a/components/investment/IndexSelicInput.vue b/app/components/investment/IndexSelicInput.vue similarity index 100% rename from components/investment/IndexSelicInput.vue rename to app/components/investment/IndexSelicInput.vue diff --git a/components/investment/PeriodInput.vue b/app/components/investment/PeriodInput.vue similarity index 100% rename from components/investment/PeriodInput.vue rename to app/components/investment/PeriodInput.vue diff --git a/components/investment/PeriodTypeInput.vue b/app/components/investment/PeriodTypeInput.vue similarity index 100% rename from components/investment/PeriodTypeInput.vue rename to app/components/investment/PeriodTypeInput.vue diff --git a/layouts/default.vue b/app/layouts/default.vue similarity index 100% rename from layouts/default.vue rename to app/layouts/default.vue diff --git a/pages/index.vue b/app/pages/index.vue similarity index 100% rename from pages/index.vue rename to app/pages/index.vue diff --git a/pages/sobre.vue b/app/pages/sobre.vue similarity index 100% rename from pages/sobre.vue rename to app/pages/sobre.vue diff --git a/plugins/vuetify.js b/app/plugins/vuetify.js similarity index 100% rename from plugins/vuetify.js rename to app/plugins/vuetify.js From ef3df8301e373519bf5b6d2a4c7ec0c28c372e68 Mon Sep 17 00:00:00 2001 From: Marcelo Wiebbelling Date: Wed, 1 Oct 2025 17:23:03 +0200 Subject: [PATCH 3/5] New directory structure --- .github/workflows/update-indexes.yml | 4 ++-- update-indexes.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/update-indexes.yml b/.github/workflows/update-indexes.yml index f81b3cb..2573f9e 100644 --- a/.github/workflows/update-indexes.yml +++ b/.github/workflows/update-indexes.yml @@ -27,7 +27,7 @@ jobs: - name: Checking for changes id: check_changes run: | - if git diff --exit-code assets/indicadores.json; then + if git diff --exit-code app/assets/indicadores.json; then echo "has_changes=false" >> $GITHUB_ENV else echo "has_changes=true" >> $GITHUB_ENV @@ -37,7 +37,7 @@ jobs: run: | git config --global user.name 'github-actions[bot]' git config --global user.email 'github-actions[bot]@users.noreply.github.com' - git add assets/indicadores.json + git add app/assets/indicadores.json git commit -m "Updated indicadores.json on $(date -u +"%Y-%m-%dT%H:%M:%SZ")" git push env: diff --git a/update-indexes.js b/update-indexes.js index 557639a..f1c274e 100644 --- a/update-indexes.js +++ b/update-indexes.js @@ -2,7 +2,7 @@ const axios = require('axios'); const fs = require('fs'); const path = require('path'); -const filePath = path.join(__dirname, 'assets', 'indicadores.json'); +const filePath = path.join(__dirname, 'app', 'assets', 'indicadores.json'); const indicadores = require(filePath); async function fetchPoupanca() { @@ -69,4 +69,4 @@ async function updateIndicadores() { } } -updateIndicadores(); \ No newline at end of file +updateIndicadores(); From bd40e4906db1591143bdcc193caed78f148c3bf1 Mon Sep 17 00:00:00 2001 From: Marcelo Wiebbelling Date: Wed, 1 Oct 2025 17:33:43 +0200 Subject: [PATCH 4/5] New directory structure --- {src => app/src}/cdb.ts | 0 {src => app/src}/finance.ts | 0 {src => app/src}/lcx.ts | 0 {src => app/src}/poupanca.ts | 0 {store => app/store}/investment.ts | 0 package.json | 5 +++-- pnpm-lock.yaml | 23 +++++++++++++---------- test/{ => app}/src/finance.spec.ts | 2 +- 8 files changed, 17 insertions(+), 13 deletions(-) rename {src => app/src}/cdb.ts (100%) rename {src => app/src}/finance.ts (100%) rename {src => app/src}/lcx.ts (100%) rename {src => app/src}/poupanca.ts (100%) rename {store => app/store}/investment.ts (100%) rename test/{ => app}/src/finance.spec.ts (98%) diff --git a/src/cdb.ts b/app/src/cdb.ts similarity index 100% rename from src/cdb.ts rename to app/src/cdb.ts diff --git a/src/finance.ts b/app/src/finance.ts similarity index 100% rename from src/finance.ts rename to app/src/finance.ts diff --git a/src/lcx.ts b/app/src/lcx.ts similarity index 100% rename from src/lcx.ts rename to app/src/lcx.ts diff --git a/src/poupanca.ts b/app/src/poupanca.ts similarity index 100% rename from src/poupanca.ts rename to app/src/poupanca.ts diff --git a/store/investment.ts b/app/store/investment.ts similarity index 100% rename from store/investment.ts rename to app/store/investment.ts diff --git a/package.json b/package.json index 81fc25b..c404793 100644 --- a/package.json +++ b/package.json @@ -22,9 +22,10 @@ }, "dependencies": { "@mdi/font": "^7.4.47", - "@pinia/nuxt": "^0.10.1", + "@pinia/nuxt": "^0.11.2", "axios": "^1.12.2", - "nuxt-schema-org": "^5.0.9" + "nuxt-schema-org": "^5.0.9", + "pinia": "^3.0.3" }, "pnpm": { "onlyBuiltDependencies": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f49872..da5b867 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,14 +12,17 @@ importers: specifier: ^7.4.47 version: 7.4.47 '@pinia/nuxt': - specifier: ^0.10.1 - version: 0.10.1(magicast@0.3.5)(pinia@3.0.1(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2))) + specifier: ^0.11.2 + version: 0.11.2(magicast@0.3.5)(pinia@3.0.3(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2))) axios: specifier: ^1.12.2 version: 1.12.2 nuxt-schema-org: specifier: ^5.0.9 version: 5.0.9(@unhead/vue@2.0.17(vue@3.5.22(typescript@5.8.2)))(h3@1.15.4)(magicast@0.3.5)(unhead@2.0.17)(vue@3.5.22(typescript@5.8.2)) + pinia: + specifier: ^3.0.3 + version: 3.0.3(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2)) devDependencies: '@nuxt/devtools': specifier: latest @@ -883,10 +886,10 @@ packages: resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} engines: {node: '>= 10.0.0'} - '@pinia/nuxt@0.10.1': - resolution: {integrity: sha512-xrpkKZHSmshPK6kQzboJ+TZiZ5zj73gBCI5SfiUaJkKKS9gx4B1hLEzJIjxZl0/HS5jRWrIvQ+u9ulvIRlNiow==} + '@pinia/nuxt@0.11.2': + resolution: {integrity: sha512-CgvSWpbktxxWBV7ModhAcsExsQZqpPq6vMYEe9DexmmY6959ev8ukL4iFhr/qov2Nb9cQAWd7niFDnaWkN+FHg==} peerDependencies: - pinia: ^3.0.1 + pinia: ^3.0.3 '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} @@ -2667,8 +2670,8 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} - pinia@3.0.1: - resolution: {integrity: sha512-WXglsDzztOTH6IfcJ99ltYZin2mY8XZCXujkYWVIJlBjqsP6ST7zw+Aarh63E1cDVYeyUcPCxPHzJpEOmzB6Wg==} + pinia@3.0.3: + resolution: {integrity: sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==} peerDependencies: typescript: '>=4.4.4' vue: ^2.7.0 || ^3.5.11 @@ -4599,10 +4602,10 @@ snapshots: '@parcel/watcher-win32-ia32': 2.5.1 '@parcel/watcher-win32-x64': 2.5.1 - '@pinia/nuxt@0.10.1(magicast@0.3.5)(pinia@3.0.1(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2)))': + '@pinia/nuxt@0.11.2(magicast@0.3.5)(pinia@3.0.3(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2)))': dependencies: '@nuxt/kit': 3.19.2(magicast@0.3.5) - pinia: 3.0.1(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2)) + pinia: 3.0.3(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2)) transitivePeerDependencies: - magicast @@ -6652,7 +6655,7 @@ snapshots: picomatch@4.0.3: {} - pinia@3.0.1(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2)): + pinia@3.0.3(typescript@5.8.2)(vue@3.5.22(typescript@5.8.2)): dependencies: '@vue/devtools-api': 7.7.7 vue: 3.5.22(typescript@5.8.2) diff --git a/test/src/finance.spec.ts b/test/app/src/finance.spec.ts similarity index 98% rename from test/src/finance.spec.ts rename to test/app/src/finance.spec.ts index 838a22b..906ff88 100644 --- a/test/src/finance.spec.ts +++ b/test/app/src/finance.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { compoundInterest, getIndexIR, getIOFAmount, getIOFPercentage } from '../../src/finance' +import { compoundInterest, getIndexIR, getIOFAmount, getIOFPercentage } from '../../../app/src/finance' describe('getIndexIR function', () => { const testCases = [ From 24c867f688ac12308252fa03620d3dfb6a25d48d Mon Sep 17 00:00:00 2001 From: Marcelo Wiebbelling Date: Wed, 1 Oct 2025 17:47:17 +0200 Subject: [PATCH 5/5] CDB Coverage --- test/app/src/cdb.spec.ts | 85 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 test/app/src/cdb.spec.ts diff --git a/test/app/src/cdb.spec.ts b/test/app/src/cdb.spec.ts new file mode 100644 index 0000000..a6b8308 --- /dev/null +++ b/test/app/src/cdb.spec.ts @@ -0,0 +1,85 @@ +import { describe, it, expect } from 'vitest' +import { getCDBResult } from '../../../app/src/cdb' +import { getIndexIR, getIOFAmount, getIOFPercentage } from '../../../app/src/finance' + +// Helper to compute expected values independently (mirrors financial math) +function expectedCDB(amount: number, di: number, yearlyIndex: number, days: number) { + const yearlyRate = yearlyIndex / 100 // convert to decimal + const dailyFactor = Math.pow((yearlyRate * di) / 100 + 1, 1 / 365) + const rawInterest = amount * Math.pow(dailyFactor, days) - amount + const interestAmount = parseFloat(rawInterest.toFixed(2)) + const taxPercentage = getIndexIR(days) + const iofAmount = getIOFAmount(days, interestAmount) + const taxAmount = (interestAmount - iofAmount) * (taxPercentage / 100) + return { interestAmount, taxAmount, taxPercentage, iofAmount } +} + +describe('getCDBResult - tax percentage tiers', () => { + const tierCases = [ + { days: 30, expected: 22.5 }, + { days: 181, expected: 20 }, + { days: 400, expected: 17.5 }, + { days: 900, expected: 15 } + ] + + for (const { days, expected } of tierCases) { + it(`returns taxPercentage ${expected} for ${days} days`, () => { + const result = getCDBResult(1000, 100, 13.15, days) + expect(result.taxPercentage).toBe(expected) + }) + } +}) + +describe('getCDBResult - IOF impact (early redemption)', () => { + it('applies IOF correctly for redemption within 10 days', () => { + const amount = 1000 + const di = 110 // 110% of CDI + const yearlyIndex = 13.15 + const days = 10 + + const result = getCDBResult(amount, di, yearlyIndex, days) + const expected = expectedCDB(amount, di, yearlyIndex, days) + + expect(getIOFPercentage(days)).toBeGreaterThan(0) // sanity check IOF applies + expect(result.interestAmount).toBe(expected.interestAmount) + expect(result.taxPercentage).toBe(expected.taxPercentage) + expect(result.iofAmount).toBeCloseTo(expected.iofAmount, 6) + expect(result.taxAmount).toBeCloseTo(expected.taxAmount, 6) + }) +}) + +describe('getCDBResult - no IOF after 35 days', () => { + it('does not apply IOF and calculates taxes correctly', () => { + const amount = 1000 + const di = 100 + const yearlyIndex = 13.15 + const days = 200 + + const result = getCDBResult(amount, di, yearlyIndex, days) + const expected = expectedCDB(amount, di, yearlyIndex, days) + + expect(getIOFPercentage(days)).toBe(0) + expect(result.iofAmount).toBe(0) + expect(result.interestAmount).toBe(expected.interestAmount) + expect(result.taxPercentage).toBe(expected.taxPercentage) + expect(result.taxAmount).toBeCloseTo(expected.taxAmount, 6) + }) +}) + +describe('getCDBResult - long term lowest tax bracket', () => { + it('applies 15% tax after more than 720 days', () => { + const amount = 1000 + const di = 95 + const yearlyIndex = 13.15 + const days = 800 + + const result = getCDBResult(amount, di, yearlyIndex, days) + const expected = expectedCDB(amount, di, yearlyIndex, days) + + expect(result.taxPercentage).toBe(15) + expect(result.iofAmount).toBe(0) + expect(result.interestAmount).toBe(expected.interestAmount) + expect(result.taxAmount).toBeCloseTo(expected.taxAmount, 6) + }) +}) +