create-huenei-frontend 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/create-huenei-frontend.js +2 -0
- package/dist/index.js +99 -0
- package/dist/templates/clean/.cursor/skills/architecture/SKILL.md +26 -0
- package/dist/templates/clean/.cursor/skills/components-shadcn/SKILL.md +23 -0
- package/dist/templates/clean/.cursor/skills/daisyui/SKILL.md +98 -0
- package/dist/templates/clean/.cursor/skills/routing/SKILL.md +32 -0
- package/dist/templates/clean/.cursor/skills/testing/SKILL.md +55 -0
- package/dist/templates/clean/.cursor/skills/tooling-and-scripts/SKILL.md +24 -0
- package/dist/templates/clean/.cursor/skills/ui-and-styling/SKILL.md +32 -0
- package/dist/templates/clean/.cursor/skills/vibe-and-ia/SKILL.md +23 -0
- package/dist/templates/clean/.prettierrc +6 -0
- package/dist/templates/clean/.tanstack/tmp/c28007bb-2319511cf318e28129c8d8eb723db5fd +9 -0
- package/dist/templates/clean/.tanstack/tmp/c28007bb-bcef89e9e4593777e1c15ec4b4f32eea +9 -0
- package/dist/templates/clean/.vscode/extensions.json +7 -0
- package/dist/templates/clean/README.md +75 -0
- package/dist/templates/clean/components.json +22 -0
- package/dist/templates/clean/eslint.config.js +31 -0
- package/dist/templates/clean/index.html +13 -0
- package/dist/templates/clean/package.json +62 -0
- package/dist/templates/clean/pnpm-lock.yaml +4487 -0
- package/dist/templates/clean/pnpm-workspace.yaml +2 -0
- package/dist/templates/clean/src/assets/react.svg +1 -0
- package/dist/templates/clean/src/components/ui/badge.tsx +37 -0
- package/dist/templates/clean/src/components/ui/breadcrumb.tsx +106 -0
- package/dist/templates/clean/src/components/ui/button.tsx +58 -0
- package/dist/templates/clean/src/components/ui/card.tsx +72 -0
- package/dist/templates/clean/src/components/ui/form.tsx +165 -0
- package/dist/templates/clean/src/components/ui/input.tsx +22 -0
- package/dist/templates/clean/src/components/ui/label.tsx +24 -0
- package/dist/templates/clean/src/components/ui/password-input.tsx +41 -0
- package/dist/templates/clean/src/components/ui/separator.tsx +28 -0
- package/dist/templates/clean/src/components/ui/tabs.tsx +62 -0
- package/dist/templates/clean/src/components/ui/textarea.tsx +21 -0
- package/dist/templates/clean/src/index.css +104 -0
- package/dist/templates/clean/src/lib/queryClient.ts +11 -0
- package/dist/templates/clean/src/lib/utils.ts +6 -0
- package/dist/templates/clean/src/main.tsx +33 -0
- package/dist/templates/clean/src/routeTree.gen.ts +77 -0
- package/dist/templates/clean/src/router.tsx +13 -0
- package/dist/templates/clean/src/routes/__root.tsx +82 -0
- package/dist/templates/clean/src/routes/index.tsx +187 -0
- package/dist/templates/clean/src/routes/otra-ruta.tsx +319 -0
- package/dist/templates/clean/src/test/setup.ts +1 -0
- package/dist/templates/clean/tsconfig.app.json +34 -0
- package/dist/templates/clean/tsconfig.json +10 -0
- package/dist/templates/clean/tsconfig.node.json +26 -0
- package/dist/templates/clean/vite.config.ts +22 -0
- package/dist/templates/clean/vitest.config.ts +9 -0
- package/dist/templates/help/.cursor/skills/architecture/SKILL.md +26 -0
- package/dist/templates/help/.cursor/skills/components-shadcn/SKILL.md +23 -0
- package/dist/templates/help/.cursor/skills/daisyui/SKILL.md +98 -0
- package/dist/templates/help/.cursor/skills/routing/SKILL.md +32 -0
- package/dist/templates/help/.cursor/skills/testing/SKILL.md +55 -0
- package/dist/templates/help/.cursor/skills/tooling-and-scripts/SKILL.md +24 -0
- package/dist/templates/help/.cursor/skills/ui-and-styling/SKILL.md +32 -0
- package/dist/templates/help/.cursor/skills/vibe-and-ia/SKILL.md +23 -0
- package/dist/templates/help/.prettierrc +6 -0
- package/dist/templates/help/.tanstack/tmp/c28007bb-2319511cf318e28129c8d8eb723db5fd +9 -0
- package/dist/templates/help/.tanstack/tmp/c28007bb-bcef89e9e4593777e1c15ec4b4f32eea +9 -0
- package/dist/templates/help/.vscode/extensions.json +7 -0
- package/dist/templates/help/README.md +75 -0
- package/dist/templates/help/components.json +22 -0
- package/dist/templates/help/eslint.config.js +31 -0
- package/dist/templates/help/index.html +13 -0
- package/dist/templates/help/package.json +62 -0
- package/dist/templates/help/pnpm-lock.yaml +4487 -0
- package/dist/templates/help/pnpm-workspace.yaml +2 -0
- package/dist/templates/help/src/assets/react.svg +1 -0
- package/dist/templates/help/src/components/documentacion/entorno.tsx +99 -0
- package/dist/templates/help/src/components/documentacion/estructura.tsx +100 -0
- package/dist/templates/help/src/components/documentacion/figma-mcp.tsx +200 -0
- package/dist/templates/help/src/components/documentacion/inicio.tsx +69 -0
- package/dist/templates/help/src/components/documentacion/instalacion.tsx +72 -0
- package/dist/templates/help/src/components/documentacion/personalizacion.tsx +163 -0
- package/dist/templates/help/src/components/documentacion/rutas.tsx +138 -0
- package/dist/templates/help/src/components/documentacion/stack.tsx +401 -0
- package/dist/templates/help/src/components/ui/badge.tsx +37 -0
- package/dist/templates/help/src/components/ui/breadcrumb.tsx +106 -0
- package/dist/templates/help/src/components/ui/button.tsx +58 -0
- package/dist/templates/help/src/components/ui/card.tsx +72 -0
- package/dist/templates/help/src/components/ui/form.tsx +165 -0
- package/dist/templates/help/src/components/ui/input.tsx +22 -0
- package/dist/templates/help/src/components/ui/label.tsx +24 -0
- package/dist/templates/help/src/components/ui/password-input.tsx +41 -0
- package/dist/templates/help/src/components/ui/separator.tsx +28 -0
- package/dist/templates/help/src/components/ui/tabs.tsx +62 -0
- package/dist/templates/help/src/components/ui/textarea.tsx +21 -0
- package/dist/templates/help/src/data/proyectos.json +56 -0
- package/dist/templates/help/src/index.css +104 -0
- package/dist/templates/help/src/lib/queryClient.ts +11 -0
- package/dist/templates/help/src/lib/utils.ts +6 -0
- package/dist/templates/help/src/main.tsx +33 -0
- package/dist/templates/help/src/routeTree.gen.ts +241 -0
- package/dist/templates/help/src/router.tsx +13 -0
- package/dist/templates/help/src/routes/__root.tsx +92 -0
- package/dist/templates/help/src/routes/auth/iniciar-sesion.tsx +139 -0
- package/dist/templates/help/src/routes/auth/registro.tsx +205 -0
- package/dist/templates/help/src/routes/contacto.tsx +60 -0
- package/dist/templates/help/src/routes/dashbord.tsx +9 -0
- package/dist/templates/help/src/routes/documentacion.tsx +80 -0
- package/dist/templates/help/src/routes/index.test.tsx +42 -0
- package/dist/templates/help/src/routes/index.tsx +211 -0
- package/dist/templates/help/src/routes/perfil.tsx +9 -0
- package/dist/templates/help/src/routes/proyectos.$proyectoId.tsx +156 -0
- package/dist/templates/help/src/routes/proyectos.tsx +93 -0
- package/dist/templates/help/src/test/setup.ts +1 -0
- package/dist/templates/help/tsconfig.app.json +34 -0
- package/dist/templates/help/tsconfig.json +10 -0
- package/dist/templates/help/tsconfig.node.json +26 -0
- package/dist/templates/help/vite.config.ts +22 -0
- package/dist/templates/help/vitest.config.ts +9 -0
- package/dist/test-cli.js +48 -0
- package/package.json +25 -0
- package/templates/clean/.cursor/skills/architecture/SKILL.md +26 -0
- package/templates/clean/.cursor/skills/components-shadcn/SKILL.md +23 -0
- package/templates/clean/.cursor/skills/daisyui/SKILL.md +98 -0
- package/templates/clean/.cursor/skills/routing/SKILL.md +32 -0
- package/templates/clean/.cursor/skills/testing/SKILL.md +55 -0
- package/templates/clean/.cursor/skills/tooling-and-scripts/SKILL.md +24 -0
- package/templates/clean/.cursor/skills/ui-and-styling/SKILL.md +32 -0
- package/templates/clean/.cursor/skills/vibe-and-ia/SKILL.md +23 -0
- package/templates/clean/.prettierrc +6 -0
- package/templates/clean/.tanstack/tmp/c28007bb-2319511cf318e28129c8d8eb723db5fd +9 -0
- package/templates/clean/.tanstack/tmp/c28007bb-bcef89e9e4593777e1c15ec4b4f32eea +9 -0
- package/templates/clean/.vscode/extensions.json +7 -0
- package/templates/clean/README.md +75 -0
- package/templates/clean/components.json +22 -0
- package/templates/clean/eslint.config.js +31 -0
- package/templates/clean/index.html +13 -0
- package/templates/clean/package.json +62 -0
- package/templates/clean/pnpm-lock.yaml +4487 -0
- package/templates/clean/pnpm-workspace.yaml +2 -0
- package/templates/clean/src/assets/react.svg +1 -0
- package/templates/clean/src/components/ui/badge.tsx +37 -0
- package/templates/clean/src/components/ui/breadcrumb.tsx +106 -0
- package/templates/clean/src/components/ui/button.tsx +58 -0
- package/templates/clean/src/components/ui/card.tsx +72 -0
- package/templates/clean/src/components/ui/form.tsx +165 -0
- package/templates/clean/src/components/ui/input.tsx +22 -0
- package/templates/clean/src/components/ui/label.tsx +24 -0
- package/templates/clean/src/components/ui/password-input.tsx +41 -0
- package/templates/clean/src/components/ui/separator.tsx +28 -0
- package/templates/clean/src/components/ui/tabs.tsx +62 -0
- package/templates/clean/src/components/ui/textarea.tsx +21 -0
- package/templates/clean/src/index.css +104 -0
- package/templates/clean/src/lib/queryClient.ts +11 -0
- package/templates/clean/src/lib/utils.ts +6 -0
- package/templates/clean/src/main.tsx +33 -0
- package/templates/clean/src/routeTree.gen.ts +77 -0
- package/templates/clean/src/router.tsx +13 -0
- package/templates/clean/src/routes/__root.tsx +82 -0
- package/templates/clean/src/routes/index.tsx +187 -0
- package/templates/clean/src/routes/otra-ruta.tsx +319 -0
- package/templates/clean/src/test/setup.ts +1 -0
- package/templates/clean/tsconfig.app.json +34 -0
- package/templates/clean/tsconfig.json +10 -0
- package/templates/clean/tsconfig.node.json +26 -0
- package/templates/clean/vite.config.ts +22 -0
- package/templates/clean/vitest.config.ts +9 -0
- package/templates/help/.cursor/skills/architecture/SKILL.md +26 -0
- package/templates/help/.cursor/skills/components-shadcn/SKILL.md +23 -0
- package/templates/help/.cursor/skills/daisyui/SKILL.md +98 -0
- package/templates/help/.cursor/skills/routing/SKILL.md +32 -0
- package/templates/help/.cursor/skills/testing/SKILL.md +55 -0
- package/templates/help/.cursor/skills/tooling-and-scripts/SKILL.md +24 -0
- package/templates/help/.cursor/skills/ui-and-styling/SKILL.md +32 -0
- package/templates/help/.cursor/skills/vibe-and-ia/SKILL.md +23 -0
- package/templates/help/.prettierrc +6 -0
- package/templates/help/.tanstack/tmp/c28007bb-2319511cf318e28129c8d8eb723db5fd +9 -0
- package/templates/help/.tanstack/tmp/c28007bb-bcef89e9e4593777e1c15ec4b4f32eea +9 -0
- package/templates/help/.vscode/extensions.json +7 -0
- package/templates/help/README.md +75 -0
- package/templates/help/components.json +22 -0
- package/templates/help/eslint.config.js +31 -0
- package/templates/help/index.html +13 -0
- package/templates/help/package.json +62 -0
- package/templates/help/pnpm-lock.yaml +4487 -0
- package/templates/help/pnpm-workspace.yaml +2 -0
- package/templates/help/src/assets/react.svg +1 -0
- package/templates/help/src/components/documentacion/entorno.tsx +99 -0
- package/templates/help/src/components/documentacion/estructura.tsx +100 -0
- package/templates/help/src/components/documentacion/figma-mcp.tsx +200 -0
- package/templates/help/src/components/documentacion/inicio.tsx +69 -0
- package/templates/help/src/components/documentacion/instalacion.tsx +72 -0
- package/templates/help/src/components/documentacion/personalizacion.tsx +163 -0
- package/templates/help/src/components/documentacion/rutas.tsx +138 -0
- package/templates/help/src/components/documentacion/stack.tsx +401 -0
- package/templates/help/src/components/ui/badge.tsx +37 -0
- package/templates/help/src/components/ui/breadcrumb.tsx +106 -0
- package/templates/help/src/components/ui/button.tsx +58 -0
- package/templates/help/src/components/ui/card.tsx +72 -0
- package/templates/help/src/components/ui/form.tsx +165 -0
- package/templates/help/src/components/ui/input.tsx +22 -0
- package/templates/help/src/components/ui/label.tsx +24 -0
- package/templates/help/src/components/ui/password-input.tsx +41 -0
- package/templates/help/src/components/ui/separator.tsx +28 -0
- package/templates/help/src/components/ui/tabs.tsx +62 -0
- package/templates/help/src/components/ui/textarea.tsx +21 -0
- package/templates/help/src/data/proyectos.json +56 -0
- package/templates/help/src/index.css +104 -0
- package/templates/help/src/lib/queryClient.ts +11 -0
- package/templates/help/src/lib/utils.ts +6 -0
- package/templates/help/src/main.tsx +33 -0
- package/templates/help/src/routeTree.gen.ts +241 -0
- package/templates/help/src/router.tsx +13 -0
- package/templates/help/src/routes/__root.tsx +92 -0
- package/templates/help/src/routes/auth/iniciar-sesion.tsx +139 -0
- package/templates/help/src/routes/auth/registro.tsx +205 -0
- package/templates/help/src/routes/contacto.tsx +60 -0
- package/templates/help/src/routes/dashbord.tsx +9 -0
- package/templates/help/src/routes/documentacion.tsx +80 -0
- package/templates/help/src/routes/index.test.tsx +42 -0
- package/templates/help/src/routes/index.tsx +211 -0
- package/templates/help/src/routes/perfil.tsx +9 -0
- package/templates/help/src/routes/proyectos.$proyectoId.tsx +156 -0
- package/templates/help/src/routes/proyectos.tsx +93 -0
- package/templates/help/src/test/setup.ts +1 -0
- package/templates/help/tsconfig.app.json +34 -0
- package/templates/help/tsconfig.json +10 -0
- package/templates/help/tsconfig.node.json +26 -0
- package/templates/help/vite.config.ts +22 -0
- package/templates/help/vitest.config.ts +9 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { createFileRoute, Link } from "@tanstack/react-router";
|
|
2
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
3
|
+
import { Badge } from "@/components/ui/badge";
|
|
4
|
+
import {
|
|
5
|
+
Route as RouteIcon,
|
|
6
|
+
FileText,
|
|
7
|
+
Code,
|
|
8
|
+
ArrowRight,
|
|
9
|
+
FolderTree,
|
|
10
|
+
Navigation,
|
|
11
|
+
Zap,
|
|
12
|
+
Shield,
|
|
13
|
+
} from "lucide-react";
|
|
14
|
+
|
|
15
|
+
export const Route = createFileRoute("/otra-ruta")({
|
|
16
|
+
component: RouteComponent,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
function RouteComponent() {
|
|
20
|
+
return (
|
|
21
|
+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
|
22
|
+
<div className="text-center mb-16">
|
|
23
|
+
<div className="flex items-center justify-center mb-6">
|
|
24
|
+
<div className="w-16 h-16 bg-primary/10 rounded-lg flex items-center justify-center">
|
|
25
|
+
<RouteIcon className="w-8 h-8 text-primary" />
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
<h1 className="text-5xl font-bold text-base-content mb-6">TanStack Router</h1>
|
|
29
|
+
<p className="text-xl text-base-content/70 max-w-3xl mx-auto mb-6">
|
|
30
|
+
Enrutamiento type-safe y file-based para aplicaciones React modernas (2026)
|
|
31
|
+
</p>
|
|
32
|
+
<div className="flex flex-wrap justify-center gap-2">
|
|
33
|
+
<Badge variant="outline">Type-Safe</Badge>
|
|
34
|
+
<Badge variant="outline">File-Based Routing</Badge>
|
|
35
|
+
<Badge variant="outline">Auto Preloading</Badge>
|
|
36
|
+
<Badge variant="outline">Code Splitting</Badge>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
{/* Conceptos Principales */}
|
|
41
|
+
<div className="grid md:grid-cols-2 gap-6 mb-16">
|
|
42
|
+
<Card className="hover:shadow-lg transition-shadow">
|
|
43
|
+
<CardHeader>
|
|
44
|
+
<div className="w-12 h-12 bg-primary/10 rounded-lg flex items-center justify-center mb-4">
|
|
45
|
+
<FolderTree className="w-6 h-6 text-primary" />
|
|
46
|
+
</div>
|
|
47
|
+
<CardTitle>File-Based Routing</CardTitle>
|
|
48
|
+
<CardDescription>
|
|
49
|
+
La estructura de archivos en <code className="text-xs">src/routes</code> define
|
|
50
|
+
automáticamente las rutas de tu aplicación
|
|
51
|
+
</CardDescription>
|
|
52
|
+
</CardHeader>
|
|
53
|
+
<CardContent>
|
|
54
|
+
<div className="space-y-3 text-sm">
|
|
55
|
+
<div className="bg-base-200 rounded-lg p-3 font-mono">
|
|
56
|
+
<div className="text-info">src/routes/</div>
|
|
57
|
+
<div className="ml-4 text-info">index.tsx</div>
|
|
58
|
+
<div className="ml-4 text-info">otra-ruta.tsx</div>
|
|
59
|
+
<div className="ml-4 text-info">proyectos.$id.tsx</div>
|
|
60
|
+
</div>
|
|
61
|
+
<p className="text-base-content/70">
|
|
62
|
+
Cada archivo se convierte en una ruta. El nombre del archivo determina la URL.
|
|
63
|
+
</p>
|
|
64
|
+
</div>
|
|
65
|
+
</CardContent>
|
|
66
|
+
</Card>
|
|
67
|
+
|
|
68
|
+
<Card className="hover:shadow-lg transition-shadow">
|
|
69
|
+
<CardHeader>
|
|
70
|
+
<div className="w-12 h-12 bg-accent/10 rounded-lg flex items-center justify-center mb-4">
|
|
71
|
+
<Shield className="w-6 h-6 text-accent" />
|
|
72
|
+
</div>
|
|
73
|
+
<CardTitle>Type Safety</CardTitle>
|
|
74
|
+
<CardDescription>
|
|
75
|
+
TypeScript garantiza que todas las rutas y parámetros sean correctos en tiempo de
|
|
76
|
+
compilación
|
|
77
|
+
</CardDescription>
|
|
78
|
+
</CardHeader>
|
|
79
|
+
<CardContent>
|
|
80
|
+
<div className="space-y-3 text-sm">
|
|
81
|
+
<div className="bg-base-200 rounded-lg p-3 font-mono text-xs">
|
|
82
|
+
<div className="text-warning">// Type-safe navigation</div>
|
|
83
|
+
<div className="text-base-content">
|
|
84
|
+
<Link to="/otra-ruta">...</Link>
|
|
85
|
+
</div>
|
|
86
|
+
<div className="text-error mt-2">// Error: ruta no existe</div>
|
|
87
|
+
<div className="text-base-content">
|
|
88
|
+
<Link to="/ruta-inexistente">...</Link>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
</CardContent>
|
|
93
|
+
</Card>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
{/* Estructura de Rutas */}
|
|
97
|
+
<Card className="mb-16">
|
|
98
|
+
<CardHeader>
|
|
99
|
+
<CardTitle className="flex items-center gap-2">
|
|
100
|
+
<FileText className="w-5 h-5" />
|
|
101
|
+
Estructura de Rutas
|
|
102
|
+
</CardTitle>
|
|
103
|
+
<CardDescription>Cómo se mapean los archivos a URLs en TanStack Router</CardDescription>
|
|
104
|
+
</CardHeader>
|
|
105
|
+
<CardContent>
|
|
106
|
+
<div className="space-y-6">
|
|
107
|
+
<div className="border-l-4 border-primary pl-4">
|
|
108
|
+
<h3 className="font-semibold mb-2">Ruta Básica</h3>
|
|
109
|
+
<div className="bg-base-200 rounded-lg p-4 font-mono text-sm mb-2">
|
|
110
|
+
<div className="text-base-content">src/routes/index.tsx</div>
|
|
111
|
+
<div className="text-info mt-2">→ URL: /</div>
|
|
112
|
+
</div>
|
|
113
|
+
<p className="text-sm text-base-content/70">
|
|
114
|
+
El archivo <code>index.tsx</code> representa la ruta raíz de su directorio.
|
|
115
|
+
</p>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div className="border-l-4 border-accent pl-4">
|
|
119
|
+
<h3 className="font-semibold mb-2">Ruta Estática</h3>
|
|
120
|
+
<div className="bg-base-200 rounded-lg p-4 font-mono text-sm mb-2">
|
|
121
|
+
<div className="text-base-content">src/routes/otra-ruta.tsx</div>
|
|
122
|
+
<div className="text-info mt-2">→ URL: /otra-ruta</div>
|
|
123
|
+
</div>
|
|
124
|
+
<p className="text-sm text-base-content/70">
|
|
125
|
+
El nombre del archivo (sin extensión) se convierte directamente en la ruta.
|
|
126
|
+
</p>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<div className="border-l-4 border-info pl-4">
|
|
130
|
+
<h3 className="font-semibold mb-2">Ruta Dinámica</h3>
|
|
131
|
+
<div className="bg-base-200 rounded-lg p-4 font-mono text-sm mb-2">
|
|
132
|
+
<div className="text-base-content">src/routes/proyectos.$proyectoId.tsx</div>
|
|
133
|
+
<div className="text-info mt-2">→ URL: /proyectos/:proyectoId</div>
|
|
134
|
+
</div>
|
|
135
|
+
<p className="text-sm text-base-content/70">
|
|
136
|
+
El prefijo <code>$</code> indica un parámetro dinámico. Accede con{" "}
|
|
137
|
+
<code>Route.useParams()</code>.
|
|
138
|
+
</p>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<div className="border-l-4 border-warning pl-4">
|
|
142
|
+
<h3 className="font-semibold mb-2">Rutas Anidadas</h3>
|
|
143
|
+
<div className="bg-base-200 rounded-lg p-4 font-mono text-sm mb-2">
|
|
144
|
+
<div className="text-base-content">src/routes/auth/iniciar-sesion.tsx</div>
|
|
145
|
+
<div className="text-info mt-2">→ URL: /auth/iniciar-sesion</div>
|
|
146
|
+
</div>
|
|
147
|
+
<p className="text-sm text-base-content/70">
|
|
148
|
+
Las carpetas crean rutas anidadas automáticamente.
|
|
149
|
+
</p>
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
</CardContent>
|
|
153
|
+
</Card>
|
|
154
|
+
|
|
155
|
+
{/* Ejemplo de Código */}
|
|
156
|
+
<Card className="mb-16">
|
|
157
|
+
<CardHeader>
|
|
158
|
+
<CardTitle className="flex items-center gap-2">
|
|
159
|
+
<Code className="w-5 h-5" />
|
|
160
|
+
Ejemplo de Implementación
|
|
161
|
+
</CardTitle>
|
|
162
|
+
<CardDescription>Cómo crear una nueva ruta en TanStack Router</CardDescription>
|
|
163
|
+
</CardHeader>
|
|
164
|
+
<CardContent>
|
|
165
|
+
<div className="space-y-4">
|
|
166
|
+
<div>
|
|
167
|
+
<h3 className="font-semibold mb-2 text-sm">1. Crear el archivo de ruta</h3>
|
|
168
|
+
<div className="bg-base-200 rounded-lg p-4 font-mono text-xs overflow-x-auto">
|
|
169
|
+
<div className="text-warning">// src/routes/mi-ruta.tsx</div>
|
|
170
|
+
<div className="text-base-content mt-2">
|
|
171
|
+
<div className="text-info">import</div> {"{"} createFileRoute {"}"}{" "}
|
|
172
|
+
<div className="text-info">from</div>{" "}
|
|
173
|
+
<div className="text-info">"@tanstack/react-router"</div>;
|
|
174
|
+
</div>
|
|
175
|
+
<div className="mt-2">
|
|
176
|
+
<div className="text-info">export const</div> Route = createFileRoute(
|
|
177
|
+
<div className="text-info">"/mi-ruta"</div>)({"{"}
|
|
178
|
+
</div>
|
|
179
|
+
<div className="ml-4">component: MiComponente,</div>
|
|
180
|
+
<div>{"});"}</div>
|
|
181
|
+
<div className="mt-2">
|
|
182
|
+
<div className="text-info">function</div> MiComponente() {"{"}
|
|
183
|
+
</div>
|
|
184
|
+
<div className="ml-4 text-info">return</div> (
|
|
185
|
+
<div className="ml-8"><div>Mi Ruta</div></div>
|
|
186
|
+
<div className="ml-4">);</div>
|
|
187
|
+
<div>{"}"}</div>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
|
|
191
|
+
<div>
|
|
192
|
+
<h3 className="font-semibold mb-2 text-sm">2. Navegar a la ruta</h3>
|
|
193
|
+
<div className="bg-base-200 rounded-lg p-4 font-mono text-xs overflow-x-auto">
|
|
194
|
+
<div className="text-info">import</div> {"{"} Link {"}"}{" "}
|
|
195
|
+
<div className="text-info">from</div>{" "}
|
|
196
|
+
<div className="text-info">"@tanstack/react-router"</div>;
|
|
197
|
+
<div className="mt-2">
|
|
198
|
+
<Link to=<div className="text-info">"/mi-ruta"</div>>
|
|
199
|
+
</div>
|
|
200
|
+
<div className="ml-4">Ir a Mi Ruta</div>
|
|
201
|
+
<div></Link></div>
|
|
202
|
+
</div>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
</CardContent>
|
|
206
|
+
</Card>
|
|
207
|
+
|
|
208
|
+
{/* Características Principales */}
|
|
209
|
+
<div className="grid md:grid-cols-3 gap-6 mb-16">
|
|
210
|
+
<Card>
|
|
211
|
+
<CardHeader>
|
|
212
|
+
<div className="w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center mb-3">
|
|
213
|
+
<Zap className="w-5 h-5 text-primary" />
|
|
214
|
+
</div>
|
|
215
|
+
<CardTitle className="text-lg">Preloading Inteligente</CardTitle>
|
|
216
|
+
</CardHeader>
|
|
217
|
+
<CardContent>
|
|
218
|
+
<p className="text-sm text-base-content/70">
|
|
219
|
+
Las rutas se precargan automáticamente cuando el usuario hace hover sobre los links,
|
|
220
|
+
mejorando la experiencia de navegación.
|
|
221
|
+
</p>
|
|
222
|
+
</CardContent>
|
|
223
|
+
</Card>
|
|
224
|
+
|
|
225
|
+
<Card>
|
|
226
|
+
<CardHeader>
|
|
227
|
+
<div className="w-10 h-10 bg-accent/10 rounded-lg flex items-center justify-center mb-3">
|
|
228
|
+
<Navigation className="w-5 h-5 text-accent" />
|
|
229
|
+
</div>
|
|
230
|
+
<CardTitle className="text-lg">Navegación Type-Safe</CardTitle>
|
|
231
|
+
</CardHeader>
|
|
232
|
+
<CardContent>
|
|
233
|
+
<p className="text-sm text-base-content/70">
|
|
234
|
+
TypeScript valida todas las rutas en tiempo de compilación, eliminando errores de
|
|
235
|
+
rutas incorrectas.
|
|
236
|
+
</p>
|
|
237
|
+
</CardContent>
|
|
238
|
+
</Card>
|
|
239
|
+
|
|
240
|
+
<Card>
|
|
241
|
+
<CardHeader>
|
|
242
|
+
<div className="w-10 h-10 bg-info/10 rounded-lg flex items-center justify-center mb-3">
|
|
243
|
+
<FileText className="w-5 h-5 text-info" />
|
|
244
|
+
</div>
|
|
245
|
+
<CardTitle className="text-lg">Code Splitting</CardTitle>
|
|
246
|
+
</CardHeader>
|
|
247
|
+
<CardContent>
|
|
248
|
+
<p className="text-sm text-base-content/70">
|
|
249
|
+
Cada ruta se carga de forma lazy automáticamente, optimizando el bundle inicial de la
|
|
250
|
+
aplicación.
|
|
251
|
+
</p>
|
|
252
|
+
</CardContent>
|
|
253
|
+
</Card>
|
|
254
|
+
</div>
|
|
255
|
+
|
|
256
|
+
{/* Mejores Prácticas */}
|
|
257
|
+
<Card className="mb-16">
|
|
258
|
+
<CardHeader>
|
|
259
|
+
<CardTitle>Mejores Prácticas</CardTitle>
|
|
260
|
+
<CardDescription>Recomendaciones para trabajar con TanStack Router</CardDescription>
|
|
261
|
+
</CardHeader>
|
|
262
|
+
<CardContent>
|
|
263
|
+
<div className="space-y-4">
|
|
264
|
+
<div className="flex gap-3">
|
|
265
|
+
<ArrowRight className="w-5 h-5 text-primary mt-0.5 shrink-0" />
|
|
266
|
+
<div>
|
|
267
|
+
<p className="font-semibold">Usar exclusivamente file-based routing</p>
|
|
268
|
+
<p className="text-sm text-base-content/70">
|
|
269
|
+
No definas rutas manualmente. Deja que TanStack Router las genere desde la
|
|
270
|
+
estructura de archivos.
|
|
271
|
+
</p>
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
<div className="flex gap-3">
|
|
275
|
+
<ArrowRight className="w-5 h-5 text-primary mt-0.5 shrink-0" />
|
|
276
|
+
<div>
|
|
277
|
+
<p className="font-semibold">Usar Link para navegación</p>
|
|
278
|
+
<p className="text-sm text-base-content/70">
|
|
279
|
+
Prefiere el componente <code>Link</code> sobre <code>useNavigate</code> para
|
|
280
|
+
mantener la type safety.
|
|
281
|
+
</p>
|
|
282
|
+
</div>
|
|
283
|
+
</div>
|
|
284
|
+
<div className="flex gap-3">
|
|
285
|
+
<ArrowRight className="w-5 h-5 text-primary mt-0.5 shrink-0" />
|
|
286
|
+
<div>
|
|
287
|
+
<p className="font-semibold">La URL es la fuente de verdad</p>
|
|
288
|
+
<p className="text-sm text-base-content/70">
|
|
289
|
+
No uses <code>useEffect</code> para sincronizar URL o params. TanStack Router lo
|
|
290
|
+
maneja automáticamente.
|
|
291
|
+
</p>
|
|
292
|
+
</div>
|
|
293
|
+
</div>
|
|
294
|
+
<div className="flex gap-3">
|
|
295
|
+
<ArrowRight className="w-5 h-5 text-primary mt-0.5 shrink-0" />
|
|
296
|
+
<div>
|
|
297
|
+
<p className="font-semibold">Loaders y Actions solo para datos</p>
|
|
298
|
+
<p className="text-sm text-base-content/70">
|
|
299
|
+
Usa loaders para cargar datos antes de renderizar y actions para mutaciones.
|
|
300
|
+
</p>
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
304
|
+
</CardContent>
|
|
305
|
+
</Card>
|
|
306
|
+
|
|
307
|
+
{/* Navegación */}
|
|
308
|
+
<div className="text-center">
|
|
309
|
+
<Link
|
|
310
|
+
to="/"
|
|
311
|
+
className="inline-flex items-center gap-2 text-primary hover:text-primary/80 transition-colors"
|
|
312
|
+
>
|
|
313
|
+
<ArrowRight className="w-4 h-4 rotate-180" />
|
|
314
|
+
Volver al inicio
|
|
315
|
+
</Link>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
);
|
|
319
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@testing-library/jest-dom'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"useDefineForClassFields": true,
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"types": ["vite/client"],
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
|
|
11
|
+
/* Paths */
|
|
12
|
+
"baseUrl": ".",
|
|
13
|
+
"paths": {
|
|
14
|
+
"@/*": ["./src/*"]
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
/* Bundler mode */
|
|
18
|
+
"moduleResolution": "bundler",
|
|
19
|
+
"allowImportingTsExtensions": true,
|
|
20
|
+
"verbatimModuleSyntax": true,
|
|
21
|
+
"moduleDetection": "force",
|
|
22
|
+
"noEmit": true,
|
|
23
|
+
"jsx": "react-jsx",
|
|
24
|
+
|
|
25
|
+
/* Linting */
|
|
26
|
+
"strict": true,
|
|
27
|
+
"noUnusedLocals": true,
|
|
28
|
+
"noUnusedParameters": true,
|
|
29
|
+
"erasableSyntaxOnly": true,
|
|
30
|
+
"noFallthroughCasesInSwitch": true,
|
|
31
|
+
"noUncheckedSideEffectImports": true
|
|
32
|
+
},
|
|
33
|
+
"include": ["src"]
|
|
34
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
4
|
+
"target": "ES2023",
|
|
5
|
+
"lib": ["ES2023"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"types": ["node"],
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
|
|
10
|
+
/* Bundler mode */
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"moduleDetection": "force",
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
/* Linting */
|
|
18
|
+
"strict": true,
|
|
19
|
+
"noUnusedLocals": true,
|
|
20
|
+
"noUnusedParameters": true,
|
|
21
|
+
"erasableSyntaxOnly": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"noUncheckedSideEffectImports": true
|
|
24
|
+
},
|
|
25
|
+
"include": ["vite.config.ts"]
|
|
26
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { defineConfig } from "vite";
|
|
3
|
+
import react from "@vitejs/plugin-react";
|
|
4
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
5
|
+
import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
|
|
6
|
+
|
|
7
|
+
export default defineConfig({
|
|
8
|
+
plugins: [
|
|
9
|
+
TanStackRouterVite({ target: 'react', autoCodeSplitting: true }),
|
|
10
|
+
react({
|
|
11
|
+
babel: {
|
|
12
|
+
plugins: [["babel-plugin-react-compiler"]],
|
|
13
|
+
},
|
|
14
|
+
}),
|
|
15
|
+
tailwindcss(),
|
|
16
|
+
],
|
|
17
|
+
resolve: {
|
|
18
|
+
alias: {
|
|
19
|
+
"@": path.resolve(__dirname, "./src"),
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Project architecture and structure
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Arquitectura del proyecto
|
|
7
|
+
|
|
8
|
+
- React 19 + TypeScript obligatorio.
|
|
9
|
+
- Vite como build tool.
|
|
10
|
+
- pnpm como gestor recomendado.
|
|
11
|
+
|
|
12
|
+
## Estructura
|
|
13
|
+
|
|
14
|
+
- `src/routes` → pantallas y navegación (TanStack Router).
|
|
15
|
+
- `src/components` → componentes reutilizables.
|
|
16
|
+
- `src/components/ui` → shadcn/ui sin lógica de negocio.
|
|
17
|
+
- `src/lib` → helpers y utilidades.
|
|
18
|
+
- `src/data` → datos estáticos.
|
|
19
|
+
- `src/assets` → recursos estáticos.
|
|
20
|
+
|
|
21
|
+
## Reglas
|
|
22
|
+
|
|
23
|
+
- Pantallas = rutas.
|
|
24
|
+
- Componentes visuales sin lógica.
|
|
25
|
+
- Lógica fuera del layout.
|
|
26
|
+
- No crear estructuras nuevas sin necesidad.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: shadcn/ui usage rules
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Componentes shadcn/ui
|
|
7
|
+
|
|
8
|
+
## Uso
|
|
9
|
+
|
|
10
|
+
- Importar desde @/components/ui
|
|
11
|
+
- Usar shadcn como base visual
|
|
12
|
+
|
|
13
|
+
## Reglas
|
|
14
|
+
|
|
15
|
+
- No modificar componentes base
|
|
16
|
+
- Extender solo vía composición
|
|
17
|
+
- Componentes UI sin lógica de negocio
|
|
18
|
+
- Mantener consistencia visual
|
|
19
|
+
|
|
20
|
+
## Instalación de nuevos componentes
|
|
21
|
+
|
|
22
|
+
- Usar el CLI oficial de shadcn
|
|
23
|
+
- No copiar código manualmente
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: DaisyUI semantic colors strictly coupled to shadcn/ui components
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DaisyUI + shadcn/ui – Reglas obligatorias
|
|
7
|
+
|
|
8
|
+
## Principio fundamental
|
|
9
|
+
|
|
10
|
+
DaisyUI **NO define componentes** en este proyecto.
|
|
11
|
+
DaisyUI **SOLO define tokens semánticos de color y theme**.
|
|
12
|
+
|
|
13
|
+
Los componentes visuales **siempre** provienen de:
|
|
14
|
+
src/components/ui (shadcn/ui)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Uso de DaisyUI
|
|
19
|
+
|
|
20
|
+
### Permitido
|
|
21
|
+
|
|
22
|
+
- Usar **únicamente** clases semánticas de color:
|
|
23
|
+
|
|
24
|
+
- bg-primary / text-primary / border-primary
|
|
25
|
+
- bg-secondary / text-secondary
|
|
26
|
+
- bg-accent
|
|
27
|
+
- bg-neutral
|
|
28
|
+
- bg-base-100 / bg-base-200 / bg-base-300
|
|
29
|
+
- text-base-content
|
|
30
|
+
|
|
31
|
+
- Usar DaisyUI para:
|
|
32
|
+
- theming
|
|
33
|
+
- color tokens
|
|
34
|
+
- soporte dark/light vía theme
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Prohibiciones absolutas
|
|
39
|
+
|
|
40
|
+
- No usar componentes DaisyUI:
|
|
41
|
+
- btn
|
|
42
|
+
- card
|
|
43
|
+
- badge
|
|
44
|
+
- alert
|
|
45
|
+
- modal
|
|
46
|
+
- tabs
|
|
47
|
+
- No importar estilos o markup de DaisyUI components.
|
|
48
|
+
- No recrear componentes shadcn usando clases DaisyUI.
|
|
49
|
+
- No usar colores hardcodeados:
|
|
50
|
+
- bg-blue-\*
|
|
51
|
+
- text-red-\*
|
|
52
|
+
- border-green-\*
|
|
53
|
+
- No usar valores hex, rgb, hsl u oklch en clases.
|
|
54
|
+
- No usar clases arbitrarias de color.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Relación con shadcn/ui
|
|
59
|
+
|
|
60
|
+
- Todo componente visual debe existir en:
|
|
61
|
+
src/components/ui
|
|
62
|
+
- Si un componente no existe:
|
|
63
|
+
- primero se crea como shadcn-compatible
|
|
64
|
+
- luego se le aplican tokens DaisyUI
|
|
65
|
+
- DaisyUI **nunca reemplaza** a shadcn/ui
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Integración con Tailwind
|
|
70
|
+
|
|
71
|
+
- Tailwind se usa para:
|
|
72
|
+
- layout
|
|
73
|
+
- spacing
|
|
74
|
+
- tipografía
|
|
75
|
+
- DaisyUI controla:
|
|
76
|
+
- colores
|
|
77
|
+
- contrastes
|
|
78
|
+
- themes
|
|
79
|
+
- shadcn/ui controla:
|
|
80
|
+
- estructura
|
|
81
|
+
- accesibilidad
|
|
82
|
+
- variantes
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Estados
|
|
87
|
+
|
|
88
|
+
- Usar tokens, no colores:
|
|
89
|
+
- hover:bg-primary-focus
|
|
90
|
+
- active:bg-primary-focus
|
|
91
|
+
- disabled:bg-base-200
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Regla final
|
|
96
|
+
|
|
97
|
+
Si un componente existe en shadcn/ui, **siempre** debe usarse.
|
|
98
|
+
Si DaisyUI ofrece algo similar, **se ignora**.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: TanStack Router rules
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Routing (TanStack Router)
|
|
7
|
+
|
|
8
|
+
## Principios
|
|
9
|
+
|
|
10
|
+
- Usar exclusivamente file-based routing
|
|
11
|
+
- Las rutas viven en src/routes
|
|
12
|
+
- La URL es fuente de verdad
|
|
13
|
+
|
|
14
|
+
## Definición de ruta
|
|
15
|
+
|
|
16
|
+
- Usar createFileRoute
|
|
17
|
+
- Un componente por archivo
|
|
18
|
+
|
|
19
|
+
## Rutas dinámicas
|
|
20
|
+
|
|
21
|
+
- Usar prefijo $ en el nombre del archivo
|
|
22
|
+
- Leer params con Route.useParams()
|
|
23
|
+
|
|
24
|
+
## Navegación
|
|
25
|
+
|
|
26
|
+
- Usar Link de @tanstack/react-router
|
|
27
|
+
- No usar useNavigate directamente
|
|
28
|
+
|
|
29
|
+
## Restricciones
|
|
30
|
+
|
|
31
|
+
- No usar useEffect para sincronizar URL o params
|
|
32
|
+
- Loaders y actions solo para datos
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Testing rules with Vitest and React Testing Library
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Testing
|
|
7
|
+
|
|
8
|
+
## Stack
|
|
9
|
+
|
|
10
|
+
- Vitest como test runner
|
|
11
|
+
- React Testing Library para testing de componentes
|
|
12
|
+
- jsdom como entorno de ejecución
|
|
13
|
+
|
|
14
|
+
## Principios
|
|
15
|
+
|
|
16
|
+
- Testear comportamiento, no implementación
|
|
17
|
+
- El test debe parecerse al uso real del usuario
|
|
18
|
+
- Priorizar claridad sobre cobertura artificial
|
|
19
|
+
|
|
20
|
+
## Reglas de React Testing Library
|
|
21
|
+
|
|
22
|
+
- Usar queries por prioridad:
|
|
23
|
+
- getByRole
|
|
24
|
+
- getByLabelText
|
|
25
|
+
- getByText
|
|
26
|
+
- Evitar:
|
|
27
|
+
- getByTestId (solo si no hay alternativa)
|
|
28
|
+
- queries por clases o estructura interna
|
|
29
|
+
|
|
30
|
+
## Componentes
|
|
31
|
+
|
|
32
|
+
- Renderizar componentes con render() de RTL
|
|
33
|
+
- No mockear componentes visuales innecesariamente
|
|
34
|
+
- Mockear solo límites externos (API, storage, router)
|
|
35
|
+
|
|
36
|
+
## Estado y efectos
|
|
37
|
+
|
|
38
|
+
- No testear estados internos directamente
|
|
39
|
+
- Verificar efectos observables en la UI
|
|
40
|
+
- Esperar cambios async con findBy\* o waitFor
|
|
41
|
+
|
|
42
|
+
## jsdom
|
|
43
|
+
|
|
44
|
+
- Asumir entorno de navegador
|
|
45
|
+
- No depender de APIs no soportadas por jsdom sin mocks
|
|
46
|
+
|
|
47
|
+
## Estructura de tests
|
|
48
|
+
|
|
49
|
+
- Un describe por unidad testeada
|
|
50
|
+
- Tests pequeños y descriptivos
|
|
51
|
+
- Evitar tests gigantes o acoplados
|
|
52
|
+
|
|
53
|
+
## Regla final
|
|
54
|
+
|
|
55
|
+
Un test que no explica qué protege, no sirve
|