Skip to content

Commit bbe6bc1

Browse files
committed
feat: added GitHub Actions CI and updated README
1 parent 4d0f056 commit bbe6bc1

File tree

7 files changed

+131
-80
lines changed

7 files changed

+131
-80
lines changed

.github/workflows/tests.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Run tests and audit
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
build-and-test:
7+
name: Install, Audit and Test app
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- name: Clone repository
12+
uses: actions/checkout@v3
13+
14+
- name: Setup Node.js
15+
uses: actions/setup-node@v3
16+
with:
17+
node-version: 20
18+
19+
- name: Install dependencies
20+
run: npm install
21+
22+
- name: Verify vulnerabilities
23+
run: npm audit --audit-level=moderate || true
24+
25+
- name: Execute unit tests
26+
run: npx vitest run src/tests/unit/userService.test.ts
27+
28+
- name: Execute integration test
29+
run: npx vitest run src/tests/integration/userApi.integration.test.ts
30+
31+
- name: Execute UI tests
32+
run: |
33+
npx vitest run src/tests/ui/addUser.ui.test.ts
34+
npx vitest run src/tests/ui/editUser.ui.test.ts
35+
npx vitest run src/tests/ui/deleteUser.ui.test.ts

README.md

Lines changed: 59 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,59 @@
1-
# user-management
2-
3-
This template should help get you started developing with Vue 3 in Vite.
4-
5-
## Recommended IDE Setup
6-
7-
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
8-
9-
## Customize configuration
10-
11-
See [Vite Configuration Reference](https://vite.dev/config/).
12-
13-
## Project Setup
14-
15-
```sh
16-
npm install
17-
```
18-
19-
### Compile and Hot-Reload for Development
20-
21-
```sh
22-
npm run dev
23-
```
24-
25-
### Compile and Minify for Production
26-
27-
```sh
28-
npm run build
29-
```
1+
# App de Gestión de Usuarios
2+
3+
Una aplicación web para la **gestión de usuarios** desarrollada en Vue y TypeScript
4+
5+
**Las funcionalidades de la app:**
6+
7+
- Listar usuarios con el total de registros
8+
- Crear, editar y eliminar usuarios
9+
- Validaciones:
10+
- Email válido
11+
- RUT único con formato
12+
- Teléfono chileno, incluyendo el código +569 o +56 9
13+
- Campos de nombre sin números
14+
- No se elimina usuarios en día de cumpleaños
15+
- Se puede añadir múltiples teléfonos y direcciones
16+
- Autenticación simulada con login
17+
18+
**Testing:**
19+
- ``Vitest`` para pruebas unitarias y de integración
20+
- ``@testing-library/vue`` para pruebas visuales (ui)
21+
- ``msw`` para mocking de la API
22+
- Autenticación: Login simulado con 'useAuth'
23+
- API Mock: Simulada mediante ``msw`` y ``db.json``
24+
25+
**Tests incluidos:**
26+
- Unit Test
27+
- UI Test
28+
- Integration Test
29+
- Mock Handlers
30+
31+
**Rutas:**
32+
33+
- '/' = login
34+
- '/home' = listados de usuarios
35+
- '/new' = formulario de crear usuario
36+
- '/edit/:id' = formulario de editar usuario
37+
38+
**Instalación y ejecución:**
39+
1. Instalar dependencias
40+
`` npm install``
41+
2. Levantar app:
42+
``npm run dev``
43+
3. Correr API fake si se usa JSON Server:
44+
``npm run api``
45+
4. Ejecutar los tests:
46+
``npx vitest run``
47+
48+
## Ejecución de pruebas individuales
49+
50+
### Prueba unitaria
51+
npx vitest run src/tests/unit/userService.test.ts
52+
53+
### Pruebas visuales (UI)
54+
- npx vitest run src/tests/ui/addUser.ui.test.ts
55+
- npx vitest run src/tests/ui/editUser.ui.test.ts
56+
- npx vitest run src/tests/ui/deleteUser.ui.test.ts
57+
58+
### Prueba de integración
59+
npx vitest run src/tests/integration/userApi.integration.test.ts

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"dev": "vite",
88
"build": "vite build",
99
"preview": "vite preview",
10-
"api": "json-server --watch db.json --port 3001"
10+
"api": "json-server --watch db.json --port 3001",
11+
"audit": "npm audit"
1112
},
1213
"dependencies": {
1314
"json-server": "^1.0.0-beta.3",

src/tests/ui/addUser.ui.test.ts

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
11
import { describe, it, expect, vi, afterEach } from "vitest";
22
import { render, screen, fireEvent, waitFor } from "@testing-library/vue";
3-
import { createRouter, createWebHistory } from "vue-router";
3+
import { testRouter } from '@/tests/utils/testRouter'
44

5-
import CreateUserView from "@/views/CreateUserView.vue";
6-
import HomeView from "@/views/HomeView.vue";
75

6+
import CreateUserView from "@/views/CreateUserView.vue";
87
import userEvent from '@testing-library/user-event'
98

10-
const router = createRouter({
11-
history: createWebHistory(),
12-
routes: [
13-
{ path: '/', component: HomeView },
14-
{ path: '/new', component: CreateUserView },
15-
],
16-
})
17-
189
afterEach(() => {
1910
vi.unstubAllGlobals();
2011
})
@@ -29,12 +20,15 @@ describe('UI -Agregar usuario', () => {
2920
json: () => Promise.resolve([]),
3021
})
3122
));
32-
23+
24+
testRouter.push('/new')
25+
await testRouter.isReady()
26+
3327
render(CreateUserView, {
3428
global: {
35-
plugins: [router],
29+
plugins: [testRouter],
3630
}
37-
})
31+
});
3832

3933
await userEvent.type(screen.getByLabelText(/RUT \*/), '12345678-5')
4034
await userEvent.type(screen.getByLabelText(/Nombre completo \*/), 'Camila Morales')
@@ -52,7 +46,7 @@ describe('UI -Agregar usuario', () => {
5246
await fireEvent.click(submitButton)
5347

5448
await waitFor(() => {
55-
expect(router.currentRoute.value.fullPath).toBe('/')
49+
expect(testRouter.currentRoute.value.fullPath).toBe('/home')
5650
})
5751
})
5852
})

src/tests/ui/deleteUser.ui.test.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { describe, it, expect, vi, afterEach } from "vitest";
22
import { render, screen, fireEvent } from "@testing-library/vue";
3-
import { createRouter, createWebHistory } from "vue-router";
43

54
import HomeView from "@/views/HomeView.vue";
6-
import CreateUserView from "@/views/CreateUserView.vue";
75
import * as userService from '@/services/userService';
86

7+
import { testRouter } from '@/tests/utils/testRouter';
8+
99

1010
const mockUsers = [
1111
{
@@ -22,14 +22,6 @@ const mockUsers = [
2222
},
2323
];
2424

25-
const router = createRouter({
26-
history: createWebHistory(),
27-
routes: [
28-
{ path: "/", component: HomeView },
29-
{ path: "/new", component: CreateUserView },
30-
],
31-
});
32-
3325
afterEach(() => {
3426
vi.restoreAllMocks();
3527
});
@@ -46,7 +38,7 @@ describe("UI - Eliminar usuario", () => {
4638

4739
render(HomeView, {
4840
global: {
49-
plugins: [router],
41+
plugins: [testRouter],
5042
},
5143
});
5244

src/tests/ui/editUser.ui.test.ts

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { describe, it, expect, vi, afterEach } from "vitest";
22
import { render, screen, fireEvent, waitFor } from "@testing-library/vue";
3-
import { createRouter, createWebHistory } from "vue-router";
43
import userEvent from "@testing-library/user-event";
4+
import { testRouter } from '@/tests/utils/testRouter'
55

66
import EditUserView from "@/views/EditUserView.vue";
7-
import HomeView from "@/views/HomeView.vue";
7+
import * as userService from '@/services/userService'
88

99
const mockUser = {
1010
id: "123",
@@ -19,14 +19,6 @@ const mockUser = {
1919
]
2020
};
2121

22-
const router = createRouter({
23-
history: createWebHistory(),
24-
routes: [
25-
{ path: "/", component: HomeView },
26-
{ path: "/edit/:id", component: EditUserView }
27-
]
28-
});
29-
3022
afterEach(() => {
3123
vi.unstubAllGlobals();
3224
});
@@ -35,23 +27,15 @@ describe("UI - Editar usuario", () => {
3527
it("Debería cargar datos y permitir editar el usuario", async () => {
3628
vi.stubGlobal("alert", vi.fn());
3729

38-
vi.stubGlobal("fetch", vi.fn((url, options) => {
39-
if (options && options.method === "PUT") {
40-
return Promise.resolve({ ok: true, json: () => Promise.resolve({}) });
41-
}
42-
43-
return Promise.resolve({
44-
ok: true,
45-
json: () => Promise.resolve([mockUser])
46-
});
47-
}));
30+
vi.spyOn(userService, "getUsers").mockResolvedValue([mockUser])
31+
vi.spyOn(userService, "updateUser").mockResolvedValue()
4832

49-
router.push("/edit/123");
50-
await router.isReady();
33+
testRouter.push("/edit/123")
34+
await testRouter.isReady()
5135

5236
render(EditUserView, {
5337
global: {
54-
plugins: [router]
38+
plugins: [testRouter]
5539
}
5640
});
5741

@@ -70,7 +54,7 @@ describe("UI - Editar usuario", () => {
7054
await fireEvent.click(submitButton);
7155

7256
await waitFor(() => {
73-
expect(router.currentRoute.value.fullPath).toBe("/");
57+
expect(testRouter.currentRoute.value.fullPath).toBe("/home");
7458
});
7559
});
7660
});

src/tests/utils/testRouter.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { createRouter, createWebHistory } from 'vue-router'
2+
import HomeView from '@/views/HomeView.vue'
3+
import CreateUserView from '@/views/CreateUserView.vue'
4+
import EditUserView from '@/views/EditUserView.vue'
5+
import LoginView from '@/views/LoginView.vue'
6+
7+
export const testRouter = createRouter({
8+
history: createWebHistory(),
9+
routes: [
10+
{ path: '/', component: LoginView },
11+
{ path: '/home', component: HomeView },
12+
{ path: '/new', component: CreateUserView },
13+
{ path: '/edit/:id', component: EditUserView },
14+
],
15+
})

0 commit comments

Comments
 (0)