diff --git a/.github/workflows/front-ci.yml b/.github/workflows/front-ci.yml index 7afaa93..2612389 100644 --- a/.github/workflows/front-ci.yml +++ b/.github/workflows/front-ci.yml @@ -108,4 +108,5 @@ jobs: echo "❌ Vite não subiu na porta 5173." exit 1 + EOF diff --git a/Stratify/babel.config.js b/Stratify/babel.config.js new file mode 100644 index 0000000..1de08c2 --- /dev/null +++ b/Stratify/babel.config.js @@ -0,0 +1,4 @@ +// babel.config.js +module.exports = { + presets: ['@babel/preset-env'] +} diff --git a/Stratify/jest.config.cjs b/Stratify/jest.config.cjs new file mode 100644 index 0000000..7994a75 --- /dev/null +++ b/Stratify/jest.config.cjs @@ -0,0 +1,12 @@ +module.exports = { + testEnvironment: 'jsdom', + moduleFileExtensions: ['js', 'json', 'vue'], + transform: { + '^.+\\.vue$': 'vue-jest', + '^.+\\.js$': 'babel-jest' + }, + moduleNameMapper: { + '^@/(.*)$': '/src/$1' + }, + testMatch: ['**/tests/unit/**/*.spec.js', '**/__tests__/**/*.spec.js'] +} diff --git a/Stratify/package.json b/Stratify/package.json index 02b474f..b75ca9d 100644 --- a/Stratify/package.json +++ b/Stratify/package.json @@ -35,16 +35,22 @@ "vue3-toastify": "^0.2.8" }, "devDependencies": { + "@babel/core": "^7.27.3", + "@babel/preset-env": "^7.27.2", "@tsconfig/node22": "^22.0.0", "@types/js-cookie": "^3.0.6", "@types/node": "^22.13.4", - "@vitejs/plugin-vue": "^5.2.1", + "@vitejs/plugin-vue": "^5.2.4", + "@vitest/coverage-v8": "^3.1.4", + "@vitest/ui": "^3.1.4", "@vue/eslint-config-typescript": "^14.4.0", + "@vue/test-utils": "^2.4.0-alpha.2", "@vue/tsconfig": "^0.7.0", "babel-jest": "^26.6.3", "c8": "^10.1.3", "eslint": "^9.20.1", "eslint-plugin-vue": "^9.32.0", + "jest": "^26.6.3", "jiti": "^2.4.2", "jsdom": "^26.1.0", "npm-run-all2": "^7.0.2", diff --git a/Stratify/src/tests/services/AverageTimeService.spec.ts b/Stratify/src/tests/services/AverageTimeService.spec.ts new file mode 100644 index 0000000..9de2597 --- /dev/null +++ b/Stratify/src/tests/services/AverageTimeService.spec.ts @@ -0,0 +1,29 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' +import AverageTimeService from '@/services/AverageTimeService' +import { api } from '@/services/apiConfig' + +vi.mock('@/services/apiConfig', () => ({ + api: { + get: vi.fn() + } +})) + +describe('AverageTimeService', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('deve buscar tempo médio com os parâmetros corretos', async () => { + (api.get as any).mockResolvedValue({ data: { tempoMedio: 4.5 } }) + + const result = await AverageTimeService.getAverageTime(1, 2) + + expect(api.get).toHaveBeenCalledWith('/fatoeficiencia/media-tempo', { + params: { + projetoId: 1, + usuarioId: 2 + } + }) + expect(result.tempoMedio).toBe(4.5) + }) +}) \ No newline at end of file diff --git a/Stratify/src/tests/services/LifeTimeService.spec.ts b/Stratify/src/tests/services/LifeTimeService.spec.ts new file mode 100644 index 0000000..ec828d6 --- /dev/null +++ b/Stratify/src/tests/services/LifeTimeService.spec.ts @@ -0,0 +1,29 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' +import lifeTimeService from '@/services/lifeTimeService' +import { api } from '@/services/apiConfig' + +vi.mock('@/services/apiConfig', () => ({ + api: { + get: vi.fn() + } +})) + +describe('LifeTimeService', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('deve buscar tempo médio com os parâmetros corretos', async () => { + (api.get as any).mockResolvedValue({ data: { tempoMedio: 4.5 } }) + + const result = await lifeTimeService.quantityPerProject(1, 2) + + expect(api.get).toHaveBeenCalledWith('/fatoeficiencia/projeto', { + params: { + projetoId: 1, + usuarioId: 2 + } + }) + expect(result.tempoMedio).toBe(4.5) + }) +}) \ No newline at end of file diff --git a/Stratify/src/tests/services/LoginService.spec.ts b/Stratify/src/tests/services/LoginService.spec.ts new file mode 100644 index 0000000..7ec1c4b --- /dev/null +++ b/Stratify/src/tests/services/LoginService.spec.ts @@ -0,0 +1,56 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' +import LoginService from '@/services/loginService' +import { api, login_api } from '@/services/apiConfig' +import tokenService from '@/services/TokenService' + +vi.mock('@/services/apiConfig', () => ({ + api: { + put: vi.fn() + }, + login_api: { + post: vi.fn() + } +})) + +vi.mock('@/services/TokenService', () => ({ + default: { + storeToken: vi.fn() + } +})) + +describe('LoginService', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('deve fazer login com email e senha válidos', async () => { + const mockToken = 'abc123token' + const mockResponse = { data: { token: mockToken }, status: 200 } + ;(login_api.post as any).mockResolvedValue(mockResponse) + + const result = await LoginService.doLogin('usuario@teste.com', 'senha123') + + expect(login_api.post).toHaveBeenCalledWith('/auth', { + email: 'usuario@teste.com', + senha: 'senha123' + }) + expect(tokenService.storeToken).toHaveBeenCalledWith(mockToken) + expect(result.token).toBe(mockToken) + }) + + it('deve lançar erro se campos estiverem vazios', async () => { + await expect(LoginService.doLogin('', '')).rejects.toThrow('Missing required fields') + }) + + it('deve resetar senha corretamente', async () => { + ;(api.put as any).mockResolvedValue({ status: 200 }) + + const result = await LoginService.changePassword(1, 'novaSenha123') + + expect(api.put).toHaveBeenCalledWith('/usuario/resetar-senha', { + idUsuario: 1, + novaSenha: 'novaSenha123' + }) + expect(result).toBe(true) + }) +}) diff --git a/Stratify/src/tests/services/UserStoryService.spec.ts b/Stratify/src/tests/services/UserStoryService.spec.ts new file mode 100644 index 0000000..e7b2312 --- /dev/null +++ b/Stratify/src/tests/services/UserStoryService.spec.ts @@ -0,0 +1,66 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' +import UserStoryService from '@/services/userStoryService' +import { api } from '@/services/apiConfig' + +vi.mock('@/services/apiConfig', () => ({ + api: { + get: vi.fn() + } +})) + +describe('UserStoryService', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('deve buscar total de cards com filtros', async () => { + const mockResponse = { data: { total: 10 } } + ;(api.get as any).mockResolvedValue(mockResponse) + + const result = await UserStoryService.getTotalCards(1, 2) + + expect(api.get).toHaveBeenCalledWith('/userStory/total-cards', { + params: { idProjeto: 1, idUsuario: 2 } + }) + expect(result.total).toBe(10) + }) + + it('deve buscar quantidade por sprint', async () => { + const mockResponse = { data: [{ sprint: 'Sprint 1', quantidade: 5 }] } + ;(api.get as any).mockResolvedValue(mockResponse) + + const result = await UserStoryService.getQuantidadePorSprint(1, 2) + + expect(api.get).toHaveBeenCalledWith('/userStory/quantidade-por-sprint', { + params: { projetoId: 1, usuarioId: 2 } + }) + expect(result[0].sprint).toBe('Sprint 1') + expect(result[0].quantidade).toBe(5) + }) + + it('deve buscar quantidade por tag', async () => { + const mockResponse = { data: [{ tag: 'Bug', quantidade: 3 }] } + ;(api.get as any).mockResolvedValue(mockResponse) + + const result = await UserStoryService.getQuantidadePorTag(1, 2) + + expect(api.get).toHaveBeenCalledWith('/userStory/quantidade-por-tag', { + params: { projetoId: 1, usuarioId: 2 } + }) + expect(result[0].tag).toBe('Bug') + expect(result[0].quantidade).toBe(3) + }) + + it('deve buscar percentual por status', async () => { + const mockResponse = { data: [{ status: 'Done', percentual: 60 }] } + ;(api.get as any).mockResolvedValue(mockResponse) + + const result = await UserStoryService.getPercentualPorStatus(1, 2) + + expect(api.get).toHaveBeenCalledWith('/userStory/percentual-por-status', { + params: { projetoId: 1, usuarioId: 2 } + }) + expect(result[0].status).toBe('Done') + expect(result[0].percentual).toBe(60) + }) +}) diff --git a/Stratify/src/tests/unit/AverageTimeIntegration.spec.ts b/Stratify/src/tests/unit/AverageTimeIntegration.spec.ts new file mode 100644 index 0000000..cb92b6c --- /dev/null +++ b/Stratify/src/tests/unit/AverageTimeIntegration.spec.ts @@ -0,0 +1,43 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' +import AverageTimeService from '@/services/AverageTimeService' +import UserStoryService from '@/services/userStoryService' +import { api } from '@/services/apiConfig' + +vi.mock('@/services/apiConfig', () => ({ + api: { + get: vi.fn() + } +})) + +describe('Integração: AverageTimeService + UserStoryService', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('deve buscar tempo médio e total de cards e calcular eficiência', async () => { + // Simula resposta do tempo médio + ;(api.get as any) + .mockResolvedValueOnce({ data: { tempoMedio: 5 } }) // AverageTimeService + .mockResolvedValueOnce({ data: { total: 20 } }) // UserStoryService + + // Chamada para os dois serviços + const tempoMedio = await AverageTimeService.getAverageTime(1, 2) + const totalCards = await UserStoryService.getTotalCards(1, 2) + + // Simulação de cálculo de eficiência (exemplo simples) + const eficiencia = totalCards.total / tempoMedio.tempoMedio + + // Verificações + expect(api.get).toHaveBeenNthCalledWith(1, '/fatoeficiencia/media-tempo', { + params: { projetoId: 1, usuarioId: 2 } + }) + + expect(api.get).toHaveBeenNthCalledWith(2, '/userStory/total-cards', { + params: { idProjeto: 1, idUsuario: 2 } + }) + + expect(tempoMedio.tempoMedio).toBe(5) + expect(totalCards.total).toBe(20) + expect(eficiencia).toBe(4) + }) +}) diff --git a/Stratify/src/tests/unit/LifeTimeIntegration.spec.ts b/Stratify/src/tests/unit/LifeTimeIntegration.spec.ts new file mode 100644 index 0000000..4c61c7a --- /dev/null +++ b/Stratify/src/tests/unit/LifeTimeIntegration.spec.ts @@ -0,0 +1,39 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' +import lifeTimeService from '@/services/lifeTimeService' +import UserStoryService from '@/services/userStoryService' +import { api } from '@/services/apiConfig' + +vi.mock('@/services/apiConfig', () => ({ + api: { + get: vi.fn() + } +})) + +describe('Integração: LifeTimeService + UserStoryService', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('deve buscar tempo médio e total de cards corretamente', async () => { + // Mocks encadeados + ;(api.get as any) + .mockResolvedValueOnce({ data: { tempoMedio: 4.5 } }) // LifeTimeService + .mockResolvedValueOnce({ data: { total: 12 } }) // UserStoryService + + // Chamada para ambos os serviços + const tempo = await lifeTimeService.quantityPerProject(1, 2) + const total = await UserStoryService.getTotalCards(1, 2) + + // Verificações + expect(api.get).toHaveBeenNthCalledWith(1, '/fatoeficiencia/projeto', { + params: { projetoId: 1, usuarioId: 2 } + }) + + expect(api.get).toHaveBeenNthCalledWith(2, '/userStory/total-cards', { + params: { idProjeto: 1, idUsuario: 2 } + }) + + expect(tempo.tempoMedio).toBe(4.5) + expect(total.total).toBe(12) + }) +}) diff --git a/Stratify/src/tests/unit/LoginIntegration.spec.ts b/Stratify/src/tests/unit/LoginIntegration.spec.ts new file mode 100644 index 0000000..9d094b8 --- /dev/null +++ b/Stratify/src/tests/unit/LoginIntegration.spec.ts @@ -0,0 +1,52 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' +import LoginService from '@/services/loginService' +import { api, login_api } from '@/services/apiConfig' +import tokenService from '@/services/TokenService' + +vi.mock('@/services/apiConfig', () => ({ + api: { + put: vi.fn() + }, + login_api: { + post: vi.fn() + } +})) + +vi.mock('@/services/TokenService', () => ({ + default: { + storeToken: vi.fn() + } +})) + +describe('LoginService - integração', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('deve fazer login e em seguida alterar a senha com sucesso', async () => { + const mockToken = 'tokenIntegracao123' + // Mock login_api.post para retornar token + ;(login_api.post as any).mockResolvedValue({ data: { token: mockToken }, status: 200 }) + // Mock api.put para alteração de senha + ;(api.put as any).mockResolvedValue({ status: 200 }) + + // Passo 1: login + const loginResult = await LoginService.doLogin('user@integ.com', 'senhaInteg') + + expect(login_api.post).toHaveBeenCalledWith('/auth', { + email: 'user@integ.com', + senha: 'senhaInteg' + }) + expect(tokenService.storeToken).toHaveBeenCalledWith(mockToken) + expect(loginResult.token).toBe(mockToken) + + // Passo 2: alterar senha + const changePassResult = await LoginService.changePassword(42, 'novaSenhaInteg') + + expect(api.put).toHaveBeenCalledWith('/usuario/resetar-senha', { + idUsuario: 42, + novaSenha: 'novaSenhaInteg' + }) + expect(changePassResult).toBe(true) + }) +}) diff --git a/Stratify/src/tests/unit/UserStoryIntegration.spec.ts b/Stratify/src/tests/unit/UserStoryIntegration.spec.ts new file mode 100644 index 0000000..dd7566c --- /dev/null +++ b/Stratify/src/tests/unit/UserStoryIntegration.spec.ts @@ -0,0 +1,55 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' +import UserStoryService from '@/services/userStoryService' +import { api } from '@/services/apiConfig' + +vi.mock('@/services/apiConfig', () => ({ + api: { + get: vi.fn() + } +})) + +describe('UserStoryService - integração', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('deve buscar total de cards, quantidade por sprint, por tag e percentual por status em conjunto', async () => { + // Respostas simuladas + const totalCardsResponse = { data: { total: 10 } } + const porSprintResponse = { data: [{ sprint: 'Sprint 1', quantidade: 5 }] } + const porTagResponse = { data: [{ tag: 'Bug', quantidade: 3 }] } + const porStatusResponse = { data: [{ status: 'Done', percentual: 60 }] } + + // Mock sequencial das chamadas (ordem importa) + ;(api.get as any) + .mockResolvedValueOnce(totalCardsResponse) + .mockResolvedValueOnce(porSprintResponse) + .mockResolvedValueOnce(porTagResponse) + .mockResolvedValueOnce(porStatusResponse) + + // Execução conjunta do fluxo + const total = await UserStoryService.getTotalCards(1, 2) + const sprint = await UserStoryService.getQuantidadePorSprint(1, 2) + const tag = await UserStoryService.getQuantidadePorTag(1, 2) + const status = await UserStoryService.getPercentualPorStatus(1, 2) + + // Verificações finais + expect(api.get).toHaveBeenNthCalledWith(1, '/userStory/total-cards', { + params: { idProjeto: 1, idUsuario: 2 } + }) + expect(api.get).toHaveBeenNthCalledWith(2, '/userStory/quantidade-por-sprint', { + params: { projetoId: 1, usuarioId: 2 } + }) + expect(api.get).toHaveBeenNthCalledWith(3, '/userStory/quantidade-por-tag', { + params: { projetoId: 1, usuarioId: 2 } + }) + expect(api.get).toHaveBeenNthCalledWith(4, '/userStory/percentual-por-status', { + params: { projetoId: 1, usuarioId: 2 } + }) + + expect(total.total).toBe(10) + expect(sprint[0]).toEqual({ sprint: 'Sprint 1', quantidade: 5 }) + expect(tag[0]).toEqual({ tag: 'Bug', quantidade: 3 }) + expect(status[0]).toEqual({ status: 'Done', percentual: 60 }) + }) +})