@vibe2founder/tests2dialects 0.1.0 → 0.2.0
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/dist/examples/imperative.spec.d.ts +1 -0
- package/dist/examples/imperative.spec.js +46 -0
- package/dist/examples/math.spec.d.ts +1 -0
- package/dist/examples/math.spec.js +39 -0
- package/dist/examples/narrative.spec.d.ts +1 -0
- package/dist/examples/narrative.spec.js +47 -0
- package/dist/examples/polyglot-shopping-cart.spec.d.ts +11 -0
- package/dist/examples/polyglot-shopping-cart.spec.js +161 -0
- package/dist/examples/sanity.spec.d.ts +1 -0
- package/dist/examples/sanity.spec.js +39 -0
- package/dist/examples/showcase-api.spec.d.ts +1 -0
- package/dist/examples/showcase-api.spec.js +62 -0
- package/dist/examples/test-api.d.ts +1 -0
- package/dist/examples/test-api.js +32 -0
- package/dist/packages/api-test-dialect/index.d.ts +28 -0
- package/dist/packages/api-test-dialect/index.js +102 -0
- package/dist/packages/reqify/index.d.ts +12 -0
- package/dist/packages/reqify/index.js +24 -0
- package/dist/src/cli.d.ts +6 -0
- package/dist/src/cli.js +330 -0
- package/dist/src/index.d.ts +134 -0
- package/dist/src/index.js +374 -0
- package/dist/src/semantic/core.d.ts +24 -0
- package/dist/src/semantic/core.js +16 -0
- package/{types/api-types.ts → dist/types/api-types.d.ts} +6 -11
- package/dist/types/api-types.js +1 -0
- package/package.json +59 -35
- package/packages/api-test-dialect/index.ts +132 -132
- package/readme.md +58 -58
- package/src/cli.ts +1 -1
- package/src/index.ts +19 -16
- package/src/semantic/core.ts +26 -0
- package/CHANGELOG.md +0 -73
- package/bun.lock +0 -22
- package/bunfig.toml +0 -2
- package/critica.md +0 -77
- package/docs/4-ideias.md +0 -66
- package/docs/api-api.md +0 -93
- package/docs/api-imperativo.md +0 -125
- package/docs/api-matematico.md +0 -145
- package/docs/api-narrativo.md +0 -181
- package/docs/guia-rapido.md +0 -189
- package/docs/whitepaper.md +0 -21
- package/examples/imperative.spec.ts +0 -58
- package/examples/math.spec.ts +0 -52
- package/examples/narrative.spec.ts +0 -61
- package/examples/polyglot-shopping-cart.spec.ts +0 -212
- package/examples/sanity.spec.ts +0 -54
- package/examples/showcase-api.spec.ts +0 -70
- package/examples/test-api.ts +0 -36
- package/infograficos/detalhado.png +0 -0
- package/infograficos/mobile.png +0 -0
- package/infograficos/normal.png +0 -0
- package/landing-page/README.md +0 -38
- package/landing-page/bun.lock +0 -609
- package/landing-page/eslint.config.js +0 -23
- package/landing-page/index.html +0 -17
- package/landing-page/package-lock.json +0 -2962
- package/landing-page/package.json +0 -34
- package/landing-page/postcss.config.js +0 -6
- package/landing-page/public/vite.svg +0 -1
- package/landing-page/src/App.tsx +0 -358
- package/landing-page/src/assets/react.svg +0 -1
- package/landing-page/src/index.css +0 -34
- package/landing-page/src/main.tsx +0 -10
- package/landing-page/tailwind.config.js +0 -59
- package/landing-page/tsconfig.app.json +0 -28
- package/landing-page/tsconfig.json +0 -7
- package/landing-page/tsconfig.node.json +0 -26
- package/landing-page/vite.config.ts +0 -7
- package/logo.png +0 -0
- package/output.log +0 -60
- package/podcast/O_Matem/303/241tico,_o_Narrador_e_o_Engenheiro.json +0 -0
- package/podcast/O_Matem/303/241tico,_o_Narrador_e_o_Engenheiro.md +0 -0
- package/podcast/critica-Dialetos_de_teste__inova/303/247/303/243o_ou_fragmenta/303/247/303/243o_.json +0 -0
- package/podcast/critica-Dialetos_de_teste__inova/303/247/303/243o_ou_fragmenta/303/247/303/243o_.md +0 -0
- package/podcast/critica-Unificar_filosofia_e_pr/303/241tica_na_documenta/303/247/303/243o_(7_words__covers_t.md +0 -1
- package/podcast/critica-Unificar_filosofia_e_pr/303/241tica_na_documenta/303/247/303/243o__7_words__covers_t.ogg +0 -0
- package/podcast/critica2-Sil/303/252ncio_estrat/303/251gico_e_sobrecarga_em_READMEs.ogg +0 -0
- package/podcast/critica2.json +0 -3191
- package/podcast/critica2.md +0 -1
- package/podcast/debate-Dialetos_de_teste__inova/303/247/303/243o_ou_fragmenta/303/247/303/243o_.json +0 -0
- package/podcast/debate-Dialetos_de_teste__inova/303/247/303/243o_ou_fragmenta/303/247/303/243o_.md +0 -0
- package/reports/01-01-2026_00-45.md +0 -40
- package/reports/01-01-2026_02-30.md +0 -37
- package/reports/03-02-2026_10-55.md +0 -8
- package/reports/03-02-2026_11-45.md +0 -13
- package/reports/03-02-2026_11-50.md +0 -10
- package/reports/26-01-2026_16-25.md +0 -31
- package/reports/26-01-2026_19-20.md +0 -27
- package/reports/31-12-2025_22-35.md +0 -25
- package/reports/31-12-2025_22-45.md +0 -15
- package/slides/Dialetos_de_Teste_Um_Executor_M/303/272ltiplos_Vocabul/303/241rios.pdf +0 -0
- package/tabela.html +0 -350
- package/tsconfig.json +0 -22
- package/www/index.html +0 -1344
package/www/index.html
DELETED
|
@@ -1,1344 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="pt-BR">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>tests2dialects Testing Framework | Interactive Explorer</title>
|
|
7
|
-
<script src="https://cdn.tailwindcss.com"></script>
|
|
8
|
-
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
9
|
-
<style>
|
|
10
|
-
/* Custom Font Import */
|
|
11
|
-
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&family=JetBrains+Mono:wght@400;700&display=swap");
|
|
12
|
-
|
|
13
|
-
body {
|
|
14
|
-
font-family: "Inter", sans-serif;
|
|
15
|
-
background-color: #f8fafc; /* Slate 50 */
|
|
16
|
-
color: #1e293b; /* Slate 800 */
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
.font-mono {
|
|
20
|
-
font-family: "JetBrains Mono", monospace;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/* Chart Container Styles - Mandatory strictly followed */
|
|
24
|
-
.chart-container {
|
|
25
|
-
position: relative;
|
|
26
|
-
width: 100%;
|
|
27
|
-
max-width: 600px;
|
|
28
|
-
margin-left: auto;
|
|
29
|
-
margin-right: auto;
|
|
30
|
-
height: 300px;
|
|
31
|
-
max-height: 400px;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
@media (min-width: 768px) {
|
|
35
|
-
.chart-container {
|
|
36
|
-
height: 350px;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/* Custom Scrollbar for code blocks */
|
|
41
|
-
.code-scroll::-webkit-scrollbar {
|
|
42
|
-
height: 8px;
|
|
43
|
-
}
|
|
44
|
-
.code-scroll::-webkit-scrollbar-track {
|
|
45
|
-
background: #1e293b;
|
|
46
|
-
}
|
|
47
|
-
.code-scroll::-webkit-scrollbar-thumb {
|
|
48
|
-
background: #475569;
|
|
49
|
-
border-radius: 4px;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/* Animations */
|
|
53
|
-
.fade-in {
|
|
54
|
-
animation: fadeIn 0.5s ease-in-out;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
@keyframes fadeIn {
|
|
58
|
-
from {
|
|
59
|
-
opacity: 0;
|
|
60
|
-
transform: translateY(10px);
|
|
61
|
-
}
|
|
62
|
-
to {
|
|
63
|
-
opacity: 1;
|
|
64
|
-
transform: translateY(0);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.tab-active {
|
|
69
|
-
border-bottom: 3px solid;
|
|
70
|
-
font-weight: 700;
|
|
71
|
-
}
|
|
72
|
-
</style>
|
|
73
|
-
<!-- Chosen Palette: Warm Neutral Background (Slate-50) with Semantic Accents: Indigo (Math), Emerald (Narrative), Amber (Imperative) -->
|
|
74
|
-
<!-- Application Structure Plan:
|
|
75
|
-
1. Hero Section: High-level overview of the "One Runner" concept.
|
|
76
|
-
2. The Philosophy Engine (Interactive Tabs): Users select a dialect (Math, Narrative, Imperative). The view updates dynamically to show the Vibe, Philosophy, Target Use Cases, and a Radar Chart visualizing the "Fit" for different testing scenarios.
|
|
77
|
-
3. The Code Morpher (Interactive Comparison): A split-view or toggle section where the user sees a "Standard Jest" snippet and watches it transform into the selected dialect, reinforcing the translation concept.
|
|
78
|
-
4. The Rosetta Stone Explorer (Data Table): A searchable/filterable table allowing users to find specific API equivalents across all dialects (e.g., filter by "Mocks" or "Assertions").
|
|
79
|
-
5. API Distribution Analysis (Chart): A bar chart visualizing the breadth of the API coverage in each category.
|
|
80
|
-
-->
|
|
81
|
-
<!-- Visualization & Content Choices:
|
|
82
|
-
1. Radar Chart (Chart.js): Visualizes "Dialect Suitability" (Logic vs. UI vs. API vs. Compliance). Helps users choose the right dialect based on their problem domain (Goal: Inform/Compare).
|
|
83
|
-
2. Bar Chart (Chart.js): Shows the count of API methods per category (Structure, Assertion, Mock, Lifecycle). visualizes the robustness of the framework (Goal: Inform).
|
|
84
|
-
3. Interactive Table (DOM Manipulation): The Rosetta Stone. Allows filtering by "Jest Equivalent" or "Category" to make the large mapping table consumable (Goal: Organize/Search).
|
|
85
|
-
4. Code Morphing Blocks (DOM Manipulation): Text updates based on state to demonstrate syntax differences without reloading (Goal: Compare/Change).
|
|
86
|
-
5. Dynamic Cards: Used for the Philosophy section to switch context without scrolling (Goal: Relationship).
|
|
87
|
-
-->
|
|
88
|
-
<!-- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->
|
|
89
|
-
</head>
|
|
90
|
-
<body class="antialiased min-h-screen flex flex-col">
|
|
91
|
-
<!-- Header / Hero -->
|
|
92
|
-
<header
|
|
93
|
-
class="bg-white border-b border-slate-200 shadow-sm sticky top-0 z-50"
|
|
94
|
-
>
|
|
95
|
-
<div
|
|
96
|
-
class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between"
|
|
97
|
-
>
|
|
98
|
-
<div class="flex items-center gap-2">
|
|
99
|
-
<span class="text-2xl">🌐</span>
|
|
100
|
-
<h1 class="text-xl font-bold tracking-tight text-slate-900">
|
|
101
|
-
tests2dialects
|
|
102
|
-
</h1>
|
|
103
|
-
</div>
|
|
104
|
-
<nav class="hidden md:flex gap-6 text-sm font-medium text-slate-600">
|
|
105
|
-
<a href="#quickstart" class="hover:text-indigo-600 transition"
|
|
106
|
-
>Quick Start</a
|
|
107
|
-
>
|
|
108
|
-
<a href="#philosophy" class="hover:text-indigo-600 transition"
|
|
109
|
-
>Filosofias</a
|
|
110
|
-
>
|
|
111
|
-
<a href="#chooser" class="hover:text-indigo-600 transition"
|
|
112
|
-
>Escolher Dialeto</a
|
|
113
|
-
>
|
|
114
|
-
<a href="#rosetta" class="hover:text-indigo-600 transition"
|
|
115
|
-
>Pedra de Roseta</a
|
|
116
|
-
>
|
|
117
|
-
<a href="#polyglot" class="hover:text-indigo-600 transition"
|
|
118
|
-
>Poliglota</a
|
|
119
|
-
>
|
|
120
|
-
</nav>
|
|
121
|
-
</div>
|
|
122
|
-
</header>
|
|
123
|
-
|
|
124
|
-
<main class="flex-grow">
|
|
125
|
-
<!-- INTRO -->
|
|
126
|
-
<section class="max-w-4xl mx-auto px-4 py-12 text-center">
|
|
127
|
-
<span
|
|
128
|
-
class="inline-block py-1 px-3 rounded-full bg-indigo-50 text-indigo-700 text-xs font-bold tracking-wide uppercase mb-4"
|
|
129
|
-
>Framework Conceitual</span
|
|
130
|
-
>
|
|
131
|
-
<h2 class="text-4xl md:text-5xl font-bold text-slate-900 mb-6">
|
|
132
|
-
One Runner to Rule Them All.
|
|
133
|
-
</h2>
|
|
134
|
-
<p class="text-lg text-slate-600 leading-relaxed mb-8">
|
|
135
|
-
O <strong>tests2dialects</strong> é uma biblioteca inovadora que
|
|
136
|
-
desacopla a lógica de execução da semântica de escrita. A linguagem
|
|
137
|
-
usada nos seus testes deve refletir a natureza do problema que você
|
|
138
|
-
está resolvendo. Algoritmo complexo? Fluxo de usuário? Contrato de
|
|
139
|
-
API? Escolha o dialeto certo.
|
|
140
|
-
</p>
|
|
141
|
-
<div class="flex flex-wrap justify-center gap-4">
|
|
142
|
-
<button
|
|
143
|
-
onclick="document.getElementById('philosophy').scrollIntoView({behavior: 'smooth'})"
|
|
144
|
-
class="bg-slate-900 text-white px-6 py-3 rounded-lg font-semibold hover:bg-slate-800 transition shadow-lg"
|
|
145
|
-
>
|
|
146
|
-
Explorar Dialetos
|
|
147
|
-
</button>
|
|
148
|
-
</div>
|
|
149
|
-
</section>
|
|
150
|
-
|
|
151
|
-
<!-- SECTION 1: PHILOSOPHY ENGINE -->
|
|
152
|
-
<section id="philosophy" class="bg-white py-16 border-t border-slate-200">
|
|
153
|
-
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
154
|
-
<div class="mb-10 max-w-2xl">
|
|
155
|
-
<h3 class="text-2xl font-bold text-slate-900 mb-2">
|
|
156
|
-
Engenharia de Filosofias
|
|
157
|
-
</h3>
|
|
158
|
-
<p class="text-slate-600">
|
|
159
|
-
Cada dialeto foi forjado com um propósito específico. Navegue
|
|
160
|
-
pelas abas abaixo para entender o "Vibe" e a aplicação ideal de
|
|
161
|
-
cada linguagem de teste disponível no framework.
|
|
162
|
-
</p>
|
|
163
|
-
</div>
|
|
164
|
-
|
|
165
|
-
<!-- Tabs -->
|
|
166
|
-
<div class="flex border-b border-slate-200 mb-8 overflow-x-auto">
|
|
167
|
-
<button
|
|
168
|
-
id="tab-math"
|
|
169
|
-
class="tab-btn px-6 py-3 text-sm font-medium text-slate-500 hover:text-indigo-600 focus:outline-none whitespace-nowrap tab-active border-indigo-600 text-indigo-600"
|
|
170
|
-
onclick="switchDialect('math')"
|
|
171
|
-
>
|
|
172
|
-
📐 O Matemático
|
|
173
|
-
</button>
|
|
174
|
-
<button
|
|
175
|
-
id="tab-narrative"
|
|
176
|
-
class="tab-btn px-6 py-3 text-sm font-medium text-slate-500 hover:text-emerald-600 focus:outline-none whitespace-nowrap"
|
|
177
|
-
onclick="switchDialect('narrative')"
|
|
178
|
-
>
|
|
179
|
-
📖 O Narrativo
|
|
180
|
-
</button>
|
|
181
|
-
<button
|
|
182
|
-
id="tab-imperative"
|
|
183
|
-
class="tab-btn px-6 py-3 text-sm font-medium text-slate-500 hover:text-amber-600 focus:outline-none whitespace-nowrap"
|
|
184
|
-
onclick="switchDialect('imperative')"
|
|
185
|
-
>
|
|
186
|
-
🛡️ O Imperativo
|
|
187
|
-
</button>
|
|
188
|
-
</div>
|
|
189
|
-
|
|
190
|
-
<!-- Dynamic Content Grid -->
|
|
191
|
-
<div
|
|
192
|
-
class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-start fade-in"
|
|
193
|
-
id="dialect-content"
|
|
194
|
-
>
|
|
195
|
-
<!-- Left: Text Info -->
|
|
196
|
-
<div>
|
|
197
|
-
<div
|
|
198
|
-
id="dialect-badge"
|
|
199
|
-
class="inline-block px-3 py-1 rounded bg-indigo-100 text-indigo-800 text-xs font-bold mb-4"
|
|
200
|
-
>
|
|
201
|
-
Lógica Formal
|
|
202
|
-
</div>
|
|
203
|
-
<h4
|
|
204
|
-
id="dialect-title"
|
|
205
|
-
class="text-3xl font-bold text-slate-900 mb-4"
|
|
206
|
-
>
|
|
207
|
-
MathDialect
|
|
208
|
-
</h4>
|
|
209
|
-
<p id="dialect-desc" class="text-slate-600 mb-6 text-lg">
|
|
210
|
-
Use este dialeto quando estiver testando algoritmos puros,
|
|
211
|
-
cálculos financeiros, regras de negócio complexas ou invariantes
|
|
212
|
-
de sistema. O teste é visto como uma <strong>prova</strong> de
|
|
213
|
-
uma verdade universal.
|
|
214
|
-
</p>
|
|
215
|
-
|
|
216
|
-
<div
|
|
217
|
-
class="bg-slate-50 rounded-xl p-6 border border-slate-200 mb-6"
|
|
218
|
-
>
|
|
219
|
-
<h5
|
|
220
|
-
class="font-bold text-slate-800 mb-3 flex items-center gap-2"
|
|
221
|
-
>
|
|
222
|
-
⚡ Vibe & Palavras-Chave
|
|
223
|
-
</h5>
|
|
224
|
-
<ul
|
|
225
|
-
id="dialect-keywords"
|
|
226
|
-
class="space-y-2 text-sm text-slate-600"
|
|
227
|
-
>
|
|
228
|
-
<li class="flex items-center gap-2">
|
|
229
|
-
<span class="text-indigo-500">➤</span> Científica, Imutável,
|
|
230
|
-
Axiomática
|
|
231
|
-
</li>
|
|
232
|
-
<li class="flex items-center gap-2">
|
|
233
|
-
<span class="text-slate-400 font-mono">Structure:</span>
|
|
234
|
-
axiom, proof
|
|
235
|
-
</li>
|
|
236
|
-
<li class="flex items-center gap-2">
|
|
237
|
-
<span class="text-slate-400 font-mono">Assert:</span>
|
|
238
|
-
implies(x).is(y)
|
|
239
|
-
</li>
|
|
240
|
-
</ul>
|
|
241
|
-
</div>
|
|
242
|
-
|
|
243
|
-
<div
|
|
244
|
-
class="bg-slate-900 rounded-xl p-6 shadow-xl overflow-hidden"
|
|
245
|
-
>
|
|
246
|
-
<div class="flex justify-between items-center mb-2">
|
|
247
|
-
<span class="text-slate-400 text-xs uppercase tracking-wider"
|
|
248
|
-
>Exemplo de Código</span
|
|
249
|
-
>
|
|
250
|
-
<div class="flex gap-1">
|
|
251
|
-
<span class="w-3 h-3 rounded-full bg-red-500"></span>
|
|
252
|
-
<span class="w-3 h-3 rounded-full bg-yellow-500"></span>
|
|
253
|
-
<span class="w-3 h-3 rounded-full bg-green-500"></span>
|
|
254
|
-
</div>
|
|
255
|
-
</div>
|
|
256
|
-
<pre
|
|
257
|
-
id="dialect-code"
|
|
258
|
-
class="font-mono text-sm text-indigo-300 overflow-x-auto code-scroll"
|
|
259
|
-
>
|
|
260
|
-
axiom("Teoria dos Números", () => {
|
|
261
|
-
const fib = arbitrary();
|
|
262
|
-
// fib é uma função arbitrária
|
|
263
|
-
fib.derive((n) => n <= 1 ? n : fib(n-1) + fib(n-2));
|
|
264
|
-
|
|
265
|
-
proof("Fibonacci(2) implica 1", () => {
|
|
266
|
-
implies(fib(2)).is(1);
|
|
267
|
-
});
|
|
268
|
-
});</pre
|
|
269
|
-
>
|
|
270
|
-
</div>
|
|
271
|
-
</div>
|
|
272
|
-
|
|
273
|
-
<!-- Right: Visualization -->
|
|
274
|
-
<div
|
|
275
|
-
class="bg-slate-50 rounded-2xl p-6 border border-slate-200 flex flex-col items-center justify-center"
|
|
276
|
-
>
|
|
277
|
-
<h5
|
|
278
|
-
class="text-sm font-bold text-slate-500 uppercase tracking-wide mb-4"
|
|
279
|
-
>
|
|
280
|
-
Adequação do Dialeto
|
|
281
|
-
</h5>
|
|
282
|
-
<div class="chart-container">
|
|
283
|
-
<canvas id="suitabilityChart"></canvas>
|
|
284
|
-
</div>
|
|
285
|
-
<p class="text-xs text-center text-slate-400 mt-4">
|
|
286
|
-
Visualização comparativa de pontos fortes por domínio.
|
|
287
|
-
</p>
|
|
288
|
-
</div>
|
|
289
|
-
</div>
|
|
290
|
-
</div>
|
|
291
|
-
</section>
|
|
292
|
-
|
|
293
|
-
<!-- SECTION 2: CODE MORPHER -->
|
|
294
|
-
<section id="morpher" class="py-16 bg-slate-50">
|
|
295
|
-
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
296
|
-
<div class="text-center mb-10">
|
|
297
|
-
<h3 class="text-2xl font-bold text-slate-900">
|
|
298
|
-
Transformação Semântica
|
|
299
|
-
</h3>
|
|
300
|
-
<p class="text-slate-600 mt-2 max-w-2xl mx-auto">
|
|
301
|
-
Veja como o mesmo teste lógico muda drasticamente de significado
|
|
302
|
-
para o leitor dependendo do dialeto escolhido.
|
|
303
|
-
</p>
|
|
304
|
-
</div>
|
|
305
|
-
|
|
306
|
-
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
307
|
-
<!-- Math Card -->
|
|
308
|
-
<div
|
|
309
|
-
class="bg-white rounded-lg shadow-sm border border-indigo-100 p-6 hover:shadow-md transition cursor-pointer group"
|
|
310
|
-
onclick="morphCode('math')"
|
|
311
|
-
>
|
|
312
|
-
<div class="flex items-center gap-3 mb-4">
|
|
313
|
-
<div
|
|
314
|
-
class="w-10 h-10 rounded-full bg-indigo-100 flex items-center justify-center text-indigo-600 font-bold text-xl group-hover:bg-indigo-600 group-hover:text-white transition"
|
|
315
|
-
>
|
|
316
|
-
📐
|
|
317
|
-
</div>
|
|
318
|
-
<h4 class="font-bold text-slate-800">Matemático</h4>
|
|
319
|
-
</div>
|
|
320
|
-
<p class="text-sm text-slate-500 mb-4">
|
|
321
|
-
Foca na verdade e na invariância.
|
|
322
|
-
</p>
|
|
323
|
-
<code
|
|
324
|
-
class="block bg-indigo-50 text-indigo-900 p-2 rounded text-xs font-mono"
|
|
325
|
-
>implies(val).is(expected)</code
|
|
326
|
-
>
|
|
327
|
-
</div>
|
|
328
|
-
|
|
329
|
-
<!-- Narrative Card -->
|
|
330
|
-
<div
|
|
331
|
-
class="bg-white rounded-lg shadow-sm border border-emerald-100 p-6 hover:shadow-md transition cursor-pointer group"
|
|
332
|
-
onclick="morphCode('narrative')"
|
|
333
|
-
>
|
|
334
|
-
<div class="flex items-center gap-3 mb-4">
|
|
335
|
-
<div
|
|
336
|
-
class="w-10 h-10 rounded-full bg-emerald-100 flex items-center justify-center text-emerald-600 font-bold text-xl group-hover:bg-emerald-600 group-hover:text-white transition"
|
|
337
|
-
>
|
|
338
|
-
📖
|
|
339
|
-
</div>
|
|
340
|
-
<h4 class="font-bold text-slate-800">Narrativo</h4>
|
|
341
|
-
</div>
|
|
342
|
-
<p class="text-sm text-slate-500 mb-4">
|
|
343
|
-
Foca no comportamento e na história.
|
|
344
|
-
</p>
|
|
345
|
-
<code
|
|
346
|
-
class="block bg-emerald-50 text-emerald-900 p-2 rounded text-xs font-mono"
|
|
347
|
-
>to(val).be(expected)</code
|
|
348
|
-
>
|
|
349
|
-
</div>
|
|
350
|
-
|
|
351
|
-
<!-- Imperative Card -->
|
|
352
|
-
<div
|
|
353
|
-
class="bg-white rounded-lg shadow-sm border border-amber-100 p-6 hover:shadow-md transition cursor-pointer group"
|
|
354
|
-
onclick="morphCode('imperative')"
|
|
355
|
-
>
|
|
356
|
-
<div class="flex items-center gap-3 mb-4">
|
|
357
|
-
<div
|
|
358
|
-
class="w-10 h-10 rounded-full bg-amber-100 flex items-center justify-center text-amber-600 font-bold text-xl group-hover:bg-amber-600 group-hover:text-white transition"
|
|
359
|
-
>
|
|
360
|
-
🛡️
|
|
361
|
-
</div>
|
|
362
|
-
<h4 class="font-bold text-slate-800">Imperativo</h4>
|
|
363
|
-
</div>
|
|
364
|
-
<p class="text-sm text-slate-500 mb-4">
|
|
365
|
-
Foca no contrato e na verificação.
|
|
366
|
-
</p>
|
|
367
|
-
<code
|
|
368
|
-
class="block bg-amber-50 text-amber-900 p-2 rounded text-xs font-mono"
|
|
369
|
-
>that(val).is(expected)</code
|
|
370
|
-
>
|
|
371
|
-
</div>
|
|
372
|
-
</div>
|
|
373
|
-
|
|
374
|
-
<!-- Active Code Block -->
|
|
375
|
-
<div
|
|
376
|
-
class="mt-8 bg-slate-900 rounded-xl p-6 shadow-2xl relative overflow-hidden max-w-3xl mx-auto"
|
|
377
|
-
>
|
|
378
|
-
<div
|
|
379
|
-
class="absolute top-0 right-0 bg-slate-800 px-3 py-1 text-xs text-slate-300 rounded-bl-lg font-mono"
|
|
380
|
-
id="morph-label"
|
|
381
|
-
>
|
|
382
|
-
CODE: MATEMÁTICO
|
|
383
|
-
</div>
|
|
384
|
-
<pre
|
|
385
|
-
class="font-mono text-sm text-slate-300 leading-relaxed overflow-x-auto"
|
|
386
|
-
id="morph-display"
|
|
387
|
-
>
|
|
388
|
-
// Carregando exemplo...
|
|
389
|
-
</pre
|
|
390
|
-
>
|
|
391
|
-
</div>
|
|
392
|
-
</div>
|
|
393
|
-
</section>
|
|
394
|
-
|
|
395
|
-
<!-- SECTION 3: ROSETTA STONE -->
|
|
396
|
-
<section id="rosetta" class="py-16 bg-white border-t border-slate-200">
|
|
397
|
-
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
398
|
-
<div
|
|
399
|
-
class="flex flex-col md:flex-row justify-between items-end mb-8 gap-4"
|
|
400
|
-
>
|
|
401
|
-
<div class="max-w-2xl">
|
|
402
|
-
<h3 class="text-2xl font-bold text-slate-900 mb-2">
|
|
403
|
-
Pedra de Roseta (Comparativo)
|
|
404
|
-
</h3>
|
|
405
|
-
<p class="text-slate-600">
|
|
406
|
-
Use esta tabela interativa para traduzir conceitos do
|
|
407
|
-
<strong>Jest</strong> para o dialeto escolhido. Filtre por
|
|
408
|
-
categoria para encontrar rapidamente a função correta.
|
|
409
|
-
</p>
|
|
410
|
-
</div>
|
|
411
|
-
<div class="w-full md:w-64">
|
|
412
|
-
<label
|
|
413
|
-
for="categoryFilter"
|
|
414
|
-
class="block text-xs font-bold text-slate-500 uppercase mb-1"
|
|
415
|
-
>Filtrar por Categoria</label
|
|
416
|
-
>
|
|
417
|
-
<select
|
|
418
|
-
id="categoryFilter"
|
|
419
|
-
onchange="filterTable()"
|
|
420
|
-
class="w-full bg-slate-50 border border-slate-300 text-slate-900 text-sm rounded-lg focus:ring-indigo-500 focus:border-indigo-500 block p-2.5"
|
|
421
|
-
>
|
|
422
|
-
<option value="all">Todas as Categorias</option>
|
|
423
|
-
<option value="Estrutura">Estrutura (Describe/Test)</option>
|
|
424
|
-
<option value="Asserção">Asserção (Expect)</option>
|
|
425
|
-
<option value="Mocks">Mocks (Criação/Spy)</option>
|
|
426
|
-
<option value="Lifecycle">Ciclo de Vida (Hooks)</option>
|
|
427
|
-
</select>
|
|
428
|
-
</div>
|
|
429
|
-
</div>
|
|
430
|
-
|
|
431
|
-
<div
|
|
432
|
-
class="overflow-x-auto shadow-lg rounded-lg border border-slate-200"
|
|
433
|
-
>
|
|
434
|
-
<table class="w-full text-left text-sm whitespace-nowrap">
|
|
435
|
-
<thead
|
|
436
|
-
class="bg-slate-100 text-slate-700 uppercase font-bold text-xs tracking-wider"
|
|
437
|
-
>
|
|
438
|
-
<tr>
|
|
439
|
-
<th class="px-6 py-4 border-b border-slate-200">Categoria</th>
|
|
440
|
-
<th class="px-6 py-4 border-b border-slate-200">
|
|
441
|
-
Jest / Conceito
|
|
442
|
-
</th>
|
|
443
|
-
<th
|
|
444
|
-
class="px-6 py-4 border-b border-slate-200 bg-indigo-50 text-indigo-900"
|
|
445
|
-
>
|
|
446
|
-
📐 Matemático
|
|
447
|
-
</th>
|
|
448
|
-
<th
|
|
449
|
-
class="px-6 py-4 border-b border-slate-200 bg-emerald-50 text-emerald-900"
|
|
450
|
-
>
|
|
451
|
-
📖 Narrativo
|
|
452
|
-
</th>
|
|
453
|
-
<th
|
|
454
|
-
class="px-6 py-4 border-b border-slate-200 bg-amber-50 text-amber-900"
|
|
455
|
-
>
|
|
456
|
-
🛡️ Imperativo
|
|
457
|
-
</th>
|
|
458
|
-
</tr>
|
|
459
|
-
</thead>
|
|
460
|
-
<tbody
|
|
461
|
-
id="rosettaBody"
|
|
462
|
-
class="bg-white divide-y divide-slate-100 font-mono text-slate-600"
|
|
463
|
-
>
|
|
464
|
-
<!-- JS Generated Rows -->
|
|
465
|
-
</tbody>
|
|
466
|
-
</table>
|
|
467
|
-
</div>
|
|
468
|
-
</div>
|
|
469
|
-
</section>
|
|
470
|
-
|
|
471
|
-
<!-- SECTION 4: API DISTRIBUTION -->
|
|
472
|
-
<section class="py-16 bg-slate-50 border-t border-slate-200">
|
|
473
|
-
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
474
|
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 items-center">
|
|
475
|
-
<div>
|
|
476
|
-
<h3 class="text-2xl font-bold text-slate-900 mb-4">
|
|
477
|
-
Cobertura da API
|
|
478
|
-
</h3>
|
|
479
|
-
<p class="text-slate-600 mb-6">
|
|
480
|
-
O tests2dialects Framework mantém paridade completa de
|
|
481
|
-
funcionalidades entre os dialetos. Não importa qual linguagem
|
|
482
|
-
você escolha, você terá acesso ao mesmo poder de mocks, spies e
|
|
483
|
-
controle de ciclo de vida. O gráfico ao lado demonstra a
|
|
484
|
-
distribuição de funções disponíveis por categoria.
|
|
485
|
-
</p>
|
|
486
|
-
<div
|
|
487
|
-
class="bg-white p-4 rounded-lg border border-slate-200 shadow-sm"
|
|
488
|
-
>
|
|
489
|
-
<div
|
|
490
|
-
class="flex items-center justify-between text-sm text-slate-500 mb-2"
|
|
491
|
-
>
|
|
492
|
-
<span>Paridade Funcional</span>
|
|
493
|
-
<span class="font-bold text-green-600">100%</span>
|
|
494
|
-
</div>
|
|
495
|
-
<div class="w-full bg-slate-200 rounded-full h-2.5">
|
|
496
|
-
<div
|
|
497
|
-
class="bg-slate-800 h-2.5 rounded-full"
|
|
498
|
-
style="width: 100%"
|
|
499
|
-
></div>
|
|
500
|
-
</div>
|
|
501
|
-
</div>
|
|
502
|
-
</div>
|
|
503
|
-
<div
|
|
504
|
-
class="bg-white p-6 rounded-xl border border-slate-200 shadow-sm flex justify-center"
|
|
505
|
-
>
|
|
506
|
-
<div class="chart-container">
|
|
507
|
-
<canvas id="distributionChart"></canvas>
|
|
508
|
-
</div>
|
|
509
|
-
</div>
|
|
510
|
-
</div>
|
|
511
|
-
</div>
|
|
512
|
-
</section>
|
|
513
|
-
|
|
514
|
-
<!-- SECTION 5: QUICK START -->
|
|
515
|
-
<section
|
|
516
|
-
id="quickstart"
|
|
517
|
-
class="py-16 bg-gradient-to-br from-indigo-900 to-slate-900 text-white"
|
|
518
|
-
>
|
|
519
|
-
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
520
|
-
<div class="text-center mb-10">
|
|
521
|
-
<span
|
|
522
|
-
class="inline-block py-1 px-3 rounded-full bg-indigo-500/20 text-indigo-300 text-xs font-bold tracking-wide uppercase mb-4"
|
|
523
|
-
>🚀 Quick Start</span
|
|
524
|
-
>
|
|
525
|
-
<h3 class="text-3xl font-bold mb-4">
|
|
526
|
-
Seu Primeiro Teste em 5 Minutos
|
|
527
|
-
</h3>
|
|
528
|
-
<p class="text-indigo-200 max-w-2xl mx-auto">
|
|
529
|
-
Antes de escolher dialetos, veja o framework em ação. Copie, cole
|
|
530
|
-
e rode.
|
|
531
|
-
</p>
|
|
532
|
-
</div>
|
|
533
|
-
|
|
534
|
-
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
|
|
535
|
-
<!-- Step 1 -->
|
|
536
|
-
<div
|
|
537
|
-
class="bg-white/10 backdrop-blur rounded-xl p-6 border border-white/20"
|
|
538
|
-
>
|
|
539
|
-
<div class="text-3xl font-bold text-indigo-400 mb-2">1</div>
|
|
540
|
-
<h4 class="font-bold text-lg mb-2">Instale</h4>
|
|
541
|
-
<code
|
|
542
|
-
class="block bg-slate-800 text-emerald-400 p-3 rounded text-sm font-mono"
|
|
543
|
-
>npm install @vibe2founder/tests2dialects</code
|
|
544
|
-
>
|
|
545
|
-
</div>
|
|
546
|
-
<!-- Step 2 -->
|
|
547
|
-
<div
|
|
548
|
-
class="bg-white/10 backdrop-blur rounded-xl p-6 border border-white/20"
|
|
549
|
-
>
|
|
550
|
-
<div class="text-3xl font-bold text-indigo-400 mb-2">2</div>
|
|
551
|
-
<h4 class="font-bold text-lg mb-2">Crie um teste</h4>
|
|
552
|
-
<p class="text-sm text-indigo-200">
|
|
553
|
-
Arquivo: <code class="text-amber-300">api.spec.ts</code>
|
|
554
|
-
</p>
|
|
555
|
-
</div>
|
|
556
|
-
<!-- Step 3 -->
|
|
557
|
-
<div
|
|
558
|
-
class="bg-white/10 backdrop-blur rounded-xl p-6 border border-white/20"
|
|
559
|
-
>
|
|
560
|
-
<div class="text-3xl font-bold text-indigo-400 mb-2">3</div>
|
|
561
|
-
<h4 class="font-bold text-lg mb-2">Execute</h4>
|
|
562
|
-
<code
|
|
563
|
-
class="block bg-slate-800 text-emerald-400 p-3 rounded text-sm font-mono"
|
|
564
|
-
>npx tests2dialects</code
|
|
565
|
-
>
|
|
566
|
-
</div>
|
|
567
|
-
</div>
|
|
568
|
-
|
|
569
|
-
<!-- Code Example -->
|
|
570
|
-
<div
|
|
571
|
-
class="bg-slate-900 rounded-xl p-6 shadow-2xl border border-slate-700"
|
|
572
|
-
>
|
|
573
|
-
<div class="flex justify-between items-center mb-4">
|
|
574
|
-
<span class="text-slate-400 text-xs uppercase tracking-wider"
|
|
575
|
-
>api.spec.ts</span
|
|
576
|
-
>
|
|
577
|
-
<div class="flex gap-1">
|
|
578
|
-
<span class="w-3 h-3 rounded-full bg-red-500"></span>
|
|
579
|
-
<span class="w-3 h-3 rounded-full bg-yellow-500"></span>
|
|
580
|
-
<span class="w-3 h-3 rounded-full bg-green-500"></span>
|
|
581
|
-
</div>
|
|
582
|
-
</div>
|
|
583
|
-
<pre class="font-mono text-sm text-amber-300 overflow-x-auto">
|
|
584
|
-
import { ensure, check, that, stub } from "@vibe2founder/tests2dialects";
|
|
585
|
-
|
|
586
|
-
ensure("Minha API de Usuários", () => {
|
|
587
|
-
const api = stub();
|
|
588
|
-
api.forceReturn({ status: 200, id: "user_123" });
|
|
589
|
-
|
|
590
|
-
check("Criação de usuário retorna 200 OK", () => {
|
|
591
|
-
const response = api.createUser({ name: "João" });
|
|
592
|
-
|
|
593
|
-
that(response.status).is(200);
|
|
594
|
-
that(response.id).matches(/^user_\w+$/);
|
|
595
|
-
});
|
|
596
|
-
});</pre
|
|
597
|
-
>
|
|
598
|
-
</div>
|
|
599
|
-
</div>
|
|
600
|
-
</section>
|
|
601
|
-
|
|
602
|
-
<!-- SECTION 6: DIALECT CHOOSER -->
|
|
603
|
-
<section id="chooser" class="py-16 bg-white border-t border-slate-200">
|
|
604
|
-
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
605
|
-
<div class="text-center mb-12">
|
|
606
|
-
<h3 class="text-2xl font-bold text-slate-900 mb-4">
|
|
607
|
-
🧭 Qual Dialeto é Para Você?
|
|
608
|
-
</h3>
|
|
609
|
-
<p class="text-slate-600 max-w-2xl mx-auto">
|
|
610
|
-
Você <strong>não precisa aprender os três</strong>. Escolha o que
|
|
611
|
-
se encaixa no seu mundo e ignore o resto. O framework é poliglota;
|
|
612
|
-
você não precisa ser.
|
|
613
|
-
</p>
|
|
614
|
-
</div>
|
|
615
|
-
|
|
616
|
-
<!-- Flowchart -->
|
|
617
|
-
<div
|
|
618
|
-
class="bg-slate-50 rounded-2xl p-8 border border-slate-200 mb-12"
|
|
619
|
-
>
|
|
620
|
-
<pre
|
|
621
|
-
class="font-mono text-xs md:text-sm text-slate-700 overflow-x-auto text-center leading-relaxed"
|
|
622
|
-
>
|
|
623
|
-
┌─────────────────────────────────────────┐
|
|
624
|
-
│ O que você está testando? │
|
|
625
|
-
└───────────────────┬─────────────────────┘
|
|
626
|
-
│
|
|
627
|
-
┌───────────────────────────────┼───────────────────────────────┐
|
|
628
|
-
│ │ │
|
|
629
|
-
▼ ▼ ▼
|
|
630
|
-
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
|
|
631
|
-
│ Algoritmos puros, │ │ Fluxos de usuário, │ │ APIs, contratos, │
|
|
632
|
-
│ cálculos, regras │ │ regras de negócio │ │ integrações, │
|
|
633
|
-
│ matemáticas? │ │ legíveis por PMs? │ │ conformidade? │
|
|
634
|
-
└──────────┬───────────┘ └──────────┬───────────┘ └──────────┬───────────┘
|
|
635
|
-
│ │ │
|
|
636
|
-
▼ ▼ ▼
|
|
637
|
-
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
|
|
638
|
-
│ 📐 MATEMÁTICO │ │ 📖 NARRATIVO │ │ 🛡️ IMPERATIVO │
|
|
639
|
-
│ axiom, proof, implies│ │ intend, scenario, to │ │ ensure, check, that │
|
|
640
|
-
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘
|
|
641
|
-
</pre>
|
|
642
|
-
</div>
|
|
643
|
-
|
|
644
|
-
<!-- Pain Point Cards -->
|
|
645
|
-
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
|
|
646
|
-
<!-- Math Pain -->
|
|
647
|
-
<div
|
|
648
|
-
class="bg-indigo-50 rounded-xl p-6 border-2 border-indigo-100 hover:border-indigo-300 transition"
|
|
649
|
-
>
|
|
650
|
-
<div class="text-3xl mb-4">📐</div>
|
|
651
|
-
<h4 class="font-bold text-indigo-900 mb-3">Dialeto Matemático</h4>
|
|
652
|
-
<div
|
|
653
|
-
class="bg-white rounded-lg p-4 mb-4 border border-indigo-100"
|
|
654
|
-
>
|
|
655
|
-
<p class="text-sm text-slate-600 mb-2">
|
|
656
|
-
<strong class="text-red-600">😤 A Dor:</strong>
|
|
657
|
-
</p>
|
|
658
|
-
<p class="text-sm text-slate-500 italic">
|
|
659
|
-
"Escrever <code>describe</code> e <code>it</code> para provar
|
|
660
|
-
um algoritmo soa informal e impreciso."
|
|
661
|
-
</p>
|
|
662
|
-
</div>
|
|
663
|
-
<div class="bg-white rounded-lg p-4 border border-indigo-100">
|
|
664
|
-
<p class="text-sm text-slate-600 mb-2">
|
|
665
|
-
<strong class="text-green-600">💡 A Solução:</strong>
|
|
666
|
-
</p>
|
|
667
|
-
<code class="text-xs text-indigo-700 font-mono"
|
|
668
|
-
>axiom("Teorema", () => proof("...", () =>
|
|
669
|
-
implies(x).is(y)))</code
|
|
670
|
-
>
|
|
671
|
-
</div>
|
|
672
|
-
</div>
|
|
673
|
-
|
|
674
|
-
<!-- Narrative Pain -->
|
|
675
|
-
<div
|
|
676
|
-
class="bg-emerald-50 rounded-xl p-6 border-2 border-emerald-100 hover:border-emerald-300 transition"
|
|
677
|
-
>
|
|
678
|
-
<div class="text-3xl mb-4">📖</div>
|
|
679
|
-
<h4 class="font-bold text-emerald-900 mb-3">Dialeto Narrativo</h4>
|
|
680
|
-
<div
|
|
681
|
-
class="bg-white rounded-lg p-4 mb-4 border border-emerald-100"
|
|
682
|
-
>
|
|
683
|
-
<p class="text-sm text-slate-600 mb-2">
|
|
684
|
-
<strong class="text-red-600">😤 A Dor:</strong>
|
|
685
|
-
</p>
|
|
686
|
-
<p class="text-sm text-slate-500 italic">
|
|
687
|
-
"Seu PM precisa validar regras de negócio, mas não consegue
|
|
688
|
-
ler seus testes."
|
|
689
|
-
</p>
|
|
690
|
-
</div>
|
|
691
|
-
<div class="bg-white rounded-lg p-4 border border-emerald-100">
|
|
692
|
-
<p class="text-sm text-slate-600 mb-2">
|
|
693
|
-
<strong class="text-green-600">💡 A Solução:</strong>
|
|
694
|
-
</p>
|
|
695
|
-
<code class="text-xs text-emerald-700 font-mono"
|
|
696
|
-
>scenario("Usuário tenta acessar...", () =>
|
|
697
|
-
to(response).be(403))</code
|
|
698
|
-
>
|
|
699
|
-
</div>
|
|
700
|
-
</div>
|
|
701
|
-
|
|
702
|
-
<!-- Imperative Pain -->
|
|
703
|
-
<div
|
|
704
|
-
class="bg-amber-50 rounded-xl p-6 border-2 border-amber-100 hover:border-amber-300 transition"
|
|
705
|
-
>
|
|
706
|
-
<div class="text-3xl mb-4">🛡️</div>
|
|
707
|
-
<h4 class="font-bold text-amber-900 mb-3">Dialeto Imperativo</h4>
|
|
708
|
-
<div class="bg-white rounded-lg p-4 mb-4 border border-amber-100">
|
|
709
|
-
<p class="text-sm text-slate-600 mb-2">
|
|
710
|
-
<strong class="text-red-600">😤 A Dor:</strong>
|
|
711
|
-
</p>
|
|
712
|
-
<p class="text-sm text-slate-500 italic">
|
|
713
|
-
"A linguagem do teste não impõe o respeito que o contrato de
|
|
714
|
-
API exige."
|
|
715
|
-
</p>
|
|
716
|
-
</div>
|
|
717
|
-
<div class="bg-white rounded-lg p-4 border border-amber-100">
|
|
718
|
-
<p class="text-sm text-slate-600 mb-2">
|
|
719
|
-
<strong class="text-green-600">💡 A Solução:</strong>
|
|
720
|
-
</p>
|
|
721
|
-
<code class="text-xs text-amber-700 font-mono"
|
|
722
|
-
>ensure("Conformidade v2", () => verify("...", () =>
|
|
723
|
-
that(x).is(y)))</code
|
|
724
|
-
>
|
|
725
|
-
</div>
|
|
726
|
-
</div>
|
|
727
|
-
</div>
|
|
728
|
-
</div>
|
|
729
|
-
</section>
|
|
730
|
-
|
|
731
|
-
<!-- SECTION 7: POLYGLOT EXAMPLE -->
|
|
732
|
-
<section id="polyglot" class="py-16 bg-slate-900 text-white">
|
|
733
|
-
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
734
|
-
<div class="text-center mb-10">
|
|
735
|
-
<span
|
|
736
|
-
class="inline-block py-1 px-3 rounded-full bg-slate-700 text-slate-300 text-xs font-bold tracking-wide uppercase mb-4"
|
|
737
|
-
>🎭 Modo Poliglota</span
|
|
738
|
-
>
|
|
739
|
-
<h3 class="text-3xl font-bold mb-4">
|
|
740
|
-
Exemplo: Carrinho de Compras (3 Dialetos)
|
|
741
|
-
</h3>
|
|
742
|
-
<p class="text-slate-400 max-w-2xl mx-auto">
|
|
743
|
-
Use cada dialeto para a camada certa. Todos no mesmo arquivo.
|
|
744
|
-
</p>
|
|
745
|
-
</div>
|
|
746
|
-
|
|
747
|
-
<!-- Layer Explanation -->
|
|
748
|
-
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
|
|
749
|
-
<div
|
|
750
|
-
class="bg-indigo-900/50 rounded-lg p-4 border border-indigo-500/30 text-center"
|
|
751
|
-
>
|
|
752
|
-
<div class="text-2xl mb-2">📐</div>
|
|
753
|
-
<p class="text-indigo-300 text-sm font-medium">
|
|
754
|
-
Cálculos de Preço
|
|
755
|
-
</p>
|
|
756
|
-
<p class="text-xs text-indigo-400">Provas matemáticas puras</p>
|
|
757
|
-
</div>
|
|
758
|
-
<div
|
|
759
|
-
class="bg-emerald-900/50 rounded-lg p-4 border border-emerald-500/30 text-center"
|
|
760
|
-
>
|
|
761
|
-
<div class="text-2xl mb-2">📖</div>
|
|
762
|
-
<p class="text-emerald-300 text-sm font-medium">
|
|
763
|
-
Jornada do Usuário
|
|
764
|
-
</p>
|
|
765
|
-
<p class="text-xs text-emerald-400">Documentação viva para PMs</p>
|
|
766
|
-
</div>
|
|
767
|
-
<div
|
|
768
|
-
class="bg-amber-900/50 rounded-lg p-4 border border-amber-500/30 text-center"
|
|
769
|
-
>
|
|
770
|
-
<div class="text-2xl mb-2">🛡️</div>
|
|
771
|
-
<p class="text-amber-300 text-sm font-medium">
|
|
772
|
-
Gateway de Pagamento
|
|
773
|
-
</p>
|
|
774
|
-
<p class="text-xs text-amber-400">Contratos rígidos de API</p>
|
|
775
|
-
</div>
|
|
776
|
-
</div>
|
|
777
|
-
|
|
778
|
-
<!-- Code -->
|
|
779
|
-
<div
|
|
780
|
-
class="bg-slate-800 rounded-xl p-6 shadow-2xl border border-slate-700 overflow-x-auto"
|
|
781
|
-
>
|
|
782
|
-
<pre
|
|
783
|
-
class="font-mono text-xs md:text-sm text-slate-300 leading-relaxed"
|
|
784
|
-
>
|
|
785
|
-
<span class="text-slate-500">// 📐 CAMADA MATEMÁTICA: Lógica Pura de Preços</span>
|
|
786
|
-
<span class="text-indigo-400">axiom</span>(<span class="text-emerald-300">"Teoria de Cálculo de Preços"</span>, () => {
|
|
787
|
-
<span class="text-indigo-400">proof</span>(<span class="text-emerald-300">"Desconto de 10% em R$100 implica R$90"</span>, () => {
|
|
788
|
-
<span class="text-indigo-400">implies</span>(calcDiscount(100, 10)).<span class="text-amber-400">is</span>(90);
|
|
789
|
-
});
|
|
790
|
-
});
|
|
791
|
-
|
|
792
|
-
<span class="text-slate-500">// 📖 CAMADA NARRATIVA: Jornada do Usuário</span>
|
|
793
|
-
<span class="text-emerald-400">intend</span>(<span class="text-emerald-300">"Jornada de Compra do Usuário"</span>, () => {
|
|
794
|
-
<span class="text-emerald-400">scenario</span>(<span class="text-emerald-300">"Usuário adiciona produto ao carrinho"</span>, () => {
|
|
795
|
-
cart.add({ name: "Camiseta", price: 49.9 });
|
|
796
|
-
<span class="text-emerald-400">to</span>(cart).<span class="text-amber-400">wasCalled</span>();
|
|
797
|
-
});
|
|
798
|
-
});
|
|
799
|
-
|
|
800
|
-
<span class="text-slate-500">// 🛡️ CAMADA IMPERATIVA: Integração com Gateway</span>
|
|
801
|
-
<span class="text-amber-400">ensure</span>(<span class="text-emerald-300">"Conformidade com Gateway de Pagamento v2.1"</span>, () => {
|
|
802
|
-
<span class="text-amber-400">check</span>(<span class="text-emerald-300">"Transação bem-sucedida retorna status 200"</span>, () => {
|
|
803
|
-
const response = paymentGateway.process({ amount: 99.9 });
|
|
804
|
-
<span class="text-amber-400">that</span>(response.status).<span class="text-amber-400">is</span>(200);
|
|
805
|
-
<span class="text-amber-400">that</span>(response.transactionId).<span class="text-amber-400">matches</span>(/^tx_[a-z0-9]+$/);
|
|
806
|
-
});
|
|
807
|
-
});
|
|
808
|
-
</pre>
|
|
809
|
-
</div>
|
|
810
|
-
<p class="text-center text-slate-500 text-sm mt-4">
|
|
811
|
-
📁 Veja o exemplo completo em
|
|
812
|
-
<code class="text-indigo-400"
|
|
813
|
-
>examples/polyglot-shopping-cart.spec.ts</code
|
|
814
|
-
>
|
|
815
|
-
</p>
|
|
816
|
-
</div>
|
|
817
|
-
</section>
|
|
818
|
-
|
|
819
|
-
<!-- SECTION 8: MIGRATION -->
|
|
820
|
-
<section
|
|
821
|
-
id="migration"
|
|
822
|
-
class="py-16 bg-emerald-50 border-t border-emerald-100"
|
|
823
|
-
>
|
|
824
|
-
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
|
825
|
-
<span
|
|
826
|
-
class="inline-block py-1 px-3 rounded-full bg-emerald-100 text-emerald-700 text-xs font-bold tracking-wide uppercase mb-4"
|
|
827
|
-
>🔄 Migração Gradual</span
|
|
828
|
-
>
|
|
829
|
-
<h3 class="text-2xl font-bold text-slate-900 mb-4">
|
|
830
|
-
Você tem 5.000 testes em Jest?
|
|
831
|
-
</h3>
|
|
832
|
-
<p class="text-slate-600 mb-8 text-lg">
|
|
833
|
-
<strong>Não reescreva nada.</strong> O tests2dialects entende
|
|
834
|
-
nativamente a sintaxe do Jest. Seu código legado continua
|
|
835
|
-
funcionando.
|
|
836
|
-
</p>
|
|
837
|
-
|
|
838
|
-
<div
|
|
839
|
-
class="bg-white rounded-xl p-6 shadow-md border border-emerald-200 text-left max-w-2xl mx-auto"
|
|
840
|
-
>
|
|
841
|
-
<pre class="font-mono text-sm overflow-x-auto">
|
|
842
|
-
<span class="text-slate-500">// ✅ Legado: Ninguém precisa mexer nisso</span>
|
|
843
|
-
<span class="text-slate-700">describe</span>(<span class="text-emerald-600">"Módulo de Login (Legacy)"</span>, () => {
|
|
844
|
-
<span class="text-slate-700">it</span>(<span class="text-emerald-600">"deve validar senha"</span>, () => {
|
|
845
|
-
<span class="text-slate-700">expect</span>(validar(<span class="text-emerald-600">"123"</span>)).toBe(<span class="text-amber-600">true</span>);
|
|
846
|
-
});
|
|
847
|
-
});
|
|
848
|
-
|
|
849
|
-
<span class="text-slate-500">// ✅ Novo: Feature nova com dialeto novo</span>
|
|
850
|
-
<span class="text-indigo-600">axiom</span>(<span class="text-emerald-600">"Nova Criptografia SHA-256"</span>, () => {
|
|
851
|
-
<span class="text-indigo-600">implies</span>(hash(<span class="text-emerald-600">"123"</span>)).matches(<span class="text-amber-600">/^[a-f0-9]{64}$/</span>);
|
|
852
|
-
});
|
|
853
|
-
</pre>
|
|
854
|
-
</div>
|
|
855
|
-
<p class="text-slate-500 text-sm mt-6">
|
|
856
|
-
Um único comando
|
|
857
|
-
<code class="bg-slate-100 px-2 py-1 rounded text-slate-700"
|
|
858
|
-
>npm test</code
|
|
859
|
-
>
|
|
860
|
-
executa <strong>ambos</strong>. Mesmo relatório. Mesma cobertura.
|
|
861
|
-
</p>
|
|
862
|
-
</div>
|
|
863
|
-
</section>
|
|
864
|
-
</main>
|
|
865
|
-
|
|
866
|
-
<footer class="bg-slate-900 text-slate-400 py-12">
|
|
867
|
-
<div class="max-w-7xl mx-auto px-4 text-center">
|
|
868
|
-
<p class="mb-4 text-2xl">🌐</p>
|
|
869
|
-
<p class="text-sm">
|
|
870
|
-
tests2dialects Testing Framework Documentation Explorer
|
|
871
|
-
</p>
|
|
872
|
-
<p class="text-xs mt-2 opacity-50">
|
|
873
|
-
Generated based on official README.md
|
|
874
|
-
</p>
|
|
875
|
-
</div>
|
|
876
|
-
</footer>
|
|
877
|
-
|
|
878
|
-
<!-- LOGIC -->
|
|
879
|
-
<script>
|
|
880
|
-
// --- DATA STORE ---
|
|
881
|
-
const dialects = {
|
|
882
|
-
math: {
|
|
883
|
-
name: "MathDialect",
|
|
884
|
-
theme: "indigo",
|
|
885
|
-
icon: "📐",
|
|
886
|
-
title: "O Matemático",
|
|
887
|
-
desc: "Baseado em Lógica Formal. Use para algoritmos puros, finanças e invariantes. O teste é uma prova.",
|
|
888
|
-
keywords: ["axiom", "proof", "implies", "arbitrary"],
|
|
889
|
-
code: `axiom("Teoria dos Números", () => {
|
|
890
|
-
const fib = arbitrary();
|
|
891
|
-
fib.derive((n) => n <= 1 ? n : fib(n-1) + fib(n-2));
|
|
892
|
-
|
|
893
|
-
proof("Fibonacci(2) implica 1", () => {
|
|
894
|
-
implies(fib(2)).is(1);
|
|
895
|
-
});
|
|
896
|
-
});`,
|
|
897
|
-
radarData: [90, 30, 60, 50, 80], // Logic, UI, API, Doc, Compliance
|
|
898
|
-
},
|
|
899
|
-
narrative: {
|
|
900
|
-
name: "NarrativeDialect",
|
|
901
|
-
theme: "emerald",
|
|
902
|
-
icon: "📖",
|
|
903
|
-
title: "O Narrativo",
|
|
904
|
-
desc: "Baseado em BDD e Storytelling. Use para fluxos de usuário (E2E) e documentação legível.",
|
|
905
|
-
keywords: ["intend", "detail", "to", "standIn"],
|
|
906
|
-
code: `intend("Sistema de Login", () => {
|
|
907
|
-
const authService = standIn();
|
|
908
|
-
authService.respondsWith(true);
|
|
909
|
-
|
|
910
|
-
detail("o usuário deve conseguir entrar", () => {
|
|
911
|
-
authService("user", "pass");
|
|
912
|
-
to(authService).received("user", "pass");
|
|
913
|
-
});
|
|
914
|
-
});`,
|
|
915
|
-
radarData: [40, 95, 60, 90, 50],
|
|
916
|
-
},
|
|
917
|
-
imperative: {
|
|
918
|
-
name: "ImperativeDialect",
|
|
919
|
-
theme: "amber",
|
|
920
|
-
icon: "🛡️",
|
|
921
|
-
title: "O Imperativo",
|
|
922
|
-
desc: "Baseado em Design by Contract. Use para integração, APIs, validação e compliance.",
|
|
923
|
-
keywords: ["ensure", "check", "that", "stub"],
|
|
924
|
-
code: `ensure("Integração Gateway", () => {
|
|
925
|
-
const api = stub();
|
|
926
|
-
api.forceReturn(200);
|
|
927
|
-
|
|
928
|
-
check("resposta respeita contrato v1", () => {
|
|
929
|
-
const status = api();
|
|
930
|
-
that(status).is(200);
|
|
931
|
-
that(api).triggered();
|
|
932
|
-
});
|
|
933
|
-
});`,
|
|
934
|
-
radarData: [60, 50, 95, 60, 95],
|
|
935
|
-
},
|
|
936
|
-
};
|
|
937
|
-
|
|
938
|
-
const rosettaData = [
|
|
939
|
-
{
|
|
940
|
-
cat: "Estrutura",
|
|
941
|
-
jest: "describe",
|
|
942
|
-
math: "axiom(name, fn)",
|
|
943
|
-
narr: "intend(name, fn) / story",
|
|
944
|
-
imp: "ensure(name, fn) / suite",
|
|
945
|
-
},
|
|
946
|
-
{
|
|
947
|
-
cat: "Estrutura",
|
|
948
|
-
jest: "test / it",
|
|
949
|
-
math: "proof(name, fn)",
|
|
950
|
-
narr: "detail(name, fn) / scenario",
|
|
951
|
-
imp: "check(name, fn) / verify",
|
|
952
|
-
},
|
|
953
|
-
{
|
|
954
|
-
cat: "Asserção",
|
|
955
|
-
jest: "expect(val).toBe",
|
|
956
|
-
math: "implies(val).is(expected)",
|
|
957
|
-
narr: "to(val).be(expected)",
|
|
958
|
-
imp: "that(val).is(expected)",
|
|
959
|
-
},
|
|
960
|
-
{
|
|
961
|
-
cat: "Asserção",
|
|
962
|
-
jest: "toHaveBeenCalled",
|
|
963
|
-
math: "implies(val).wasEvaluated()",
|
|
964
|
-
narr: "to(val).wasCalled()",
|
|
965
|
-
imp: "that(val).triggered()",
|
|
966
|
-
},
|
|
967
|
-
{
|
|
968
|
-
cat: "Asserção",
|
|
969
|
-
jest: "toHaveBeenCalledWith",
|
|
970
|
-
math: "implies(val).appliedTo(args)",
|
|
971
|
-
narr: "to(val).received(args)",
|
|
972
|
-
imp: "that(val).calledWith(args)",
|
|
973
|
-
},
|
|
974
|
-
{
|
|
975
|
-
cat: "Mocks",
|
|
976
|
-
jest: "jest.fn()",
|
|
977
|
-
math: "arbitrary() / lambda()",
|
|
978
|
-
narr: "dummy() / standIn()",
|
|
979
|
-
imp: "stub() / mock()",
|
|
980
|
-
},
|
|
981
|
-
{
|
|
982
|
-
cat: "Mocks",
|
|
983
|
-
jest: "jest.spyOn()",
|
|
984
|
-
math: "monitor(obj, method)",
|
|
985
|
-
narr: "watch / shadow",
|
|
986
|
-
imp: "inspect / spy",
|
|
987
|
-
},
|
|
988
|
-
{
|
|
989
|
-
cat: "Mocks",
|
|
990
|
-
jest: "mockReturnValue",
|
|
991
|
-
math: "f.yields(val)",
|
|
992
|
-
narr: "actor.respondsWith(val)",
|
|
993
|
-
imp: "s.forceReturn(val)",
|
|
994
|
-
},
|
|
995
|
-
{
|
|
996
|
-
cat: "Mocks",
|
|
997
|
-
jest: "mockResolvedValue",
|
|
998
|
-
math: "f.convergesTo(val)",
|
|
999
|
-
narr: "actor.eventuallyGives(val)",
|
|
1000
|
-
imp: "s.resolveWith(val)",
|
|
1001
|
-
},
|
|
1002
|
-
{
|
|
1003
|
-
cat: "Mocks",
|
|
1004
|
-
jest: "mockImplementation",
|
|
1005
|
-
math: "f.derive(fn)",
|
|
1006
|
-
narr: "actor.actsLike(fn)",
|
|
1007
|
-
imp: "s.executes(fn)",
|
|
1008
|
-
},
|
|
1009
|
-
{
|
|
1010
|
-
cat: "Lifecycle",
|
|
1011
|
-
jest: "beforeAll",
|
|
1012
|
-
math: "postulate(fn)",
|
|
1013
|
-
narr: "background(fn)",
|
|
1014
|
-
imp: "initAll(fn)",
|
|
1015
|
-
},
|
|
1016
|
-
{
|
|
1017
|
-
cat: "Lifecycle",
|
|
1018
|
-
jest: "beforeEach",
|
|
1019
|
-
math: "given(fn)",
|
|
1020
|
-
narr: "before(fn)",
|
|
1021
|
-
imp: "reset(fn)",
|
|
1022
|
-
},
|
|
1023
|
-
{
|
|
1024
|
-
cat: "Lifecycle",
|
|
1025
|
-
jest: "afterAll",
|
|
1026
|
-
math: "conclude(fn)",
|
|
1027
|
-
narr: "cleanup(fn)",
|
|
1028
|
-
imp: "disposeAll(fn)",
|
|
1029
|
-
},
|
|
1030
|
-
];
|
|
1031
|
-
|
|
1032
|
-
// --- STATE & CHARTS ---
|
|
1033
|
-
let currentChart = null;
|
|
1034
|
-
let distributionChart = null;
|
|
1035
|
-
|
|
1036
|
-
// --- INITIALIZATION ---
|
|
1037
|
-
window.onload = function () {
|
|
1038
|
-
renderRosettaTable("all");
|
|
1039
|
-
initCharts();
|
|
1040
|
-
morphCode("math"); // Start with default
|
|
1041
|
-
};
|
|
1042
|
-
|
|
1043
|
-
// --- INTERACTION LOGIC ---
|
|
1044
|
-
|
|
1045
|
-
// ELASTIC NAVIGATION (Smooth Scroll)
|
|
1046
|
-
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
|
|
1047
|
-
anchor.addEventListener("click", function (e) {
|
|
1048
|
-
e.preventDefault();
|
|
1049
|
-
const targetId = this.getAttribute("href");
|
|
1050
|
-
const targetElement = document.querySelector(targetId);
|
|
1051
|
-
if (targetElement) {
|
|
1052
|
-
elasticScrollTo(targetElement, 1200);
|
|
1053
|
-
}
|
|
1054
|
-
});
|
|
1055
|
-
});
|
|
1056
|
-
|
|
1057
|
-
function elasticScrollTo(element, duration) {
|
|
1058
|
-
const headerOffset = 80; // Space for the sticky header
|
|
1059
|
-
const elementPosition = element.getBoundingClientRect().top;
|
|
1060
|
-
const startPosition = window.pageYOffset;
|
|
1061
|
-
const offsetPosition = elementPosition + startPosition - headerOffset;
|
|
1062
|
-
const distance = offsetPosition - startPosition;
|
|
1063
|
-
let startTime = null;
|
|
1064
|
-
|
|
1065
|
-
function animation(currentTime) {
|
|
1066
|
-
if (startTime === null) startTime = currentTime;
|
|
1067
|
-
const timeElapsed = currentTime - startTime;
|
|
1068
|
-
const run = easeOutElastic(
|
|
1069
|
-
timeElapsed,
|
|
1070
|
-
startPosition,
|
|
1071
|
-
distance,
|
|
1072
|
-
duration
|
|
1073
|
-
);
|
|
1074
|
-
window.scrollTo(0, run);
|
|
1075
|
-
|
|
1076
|
-
if (timeElapsed < duration) requestAnimationFrame(animation);
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
// Elastic Easing Function (The "Bouncy" Logic)
|
|
1080
|
-
function easeOutElastic(t, b, c, d) {
|
|
1081
|
-
var s = 1.70158;
|
|
1082
|
-
var p = 0;
|
|
1083
|
-
var a = c;
|
|
1084
|
-
if (t == 0) return b;
|
|
1085
|
-
if ((t /= d) == 1) return b + c;
|
|
1086
|
-
if (!p) p = d * 0.3;
|
|
1087
|
-
if (a < Math.abs(c)) {
|
|
1088
|
-
a = c;
|
|
1089
|
-
var s = p / 4;
|
|
1090
|
-
} else var s = (p / (2 * Math.PI)) * Math.asin(c / a);
|
|
1091
|
-
return (
|
|
1092
|
-
a *
|
|
1093
|
-
Math.pow(2, -10 * t) *
|
|
1094
|
-
Math.sin(((t * d - s) * (2 * Math.PI)) / p) +
|
|
1095
|
-
c +
|
|
1096
|
-
b
|
|
1097
|
-
);
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
// Alternative: Less aggressive "Exponential" for smoother pro feel if elastic is too much
|
|
1101
|
-
// But user requested "Elastic".
|
|
1102
|
-
// Let's use a modified easeInOutQuint for "premium elastic" feel without dizziness
|
|
1103
|
-
function easeInOutQuint(t, b, c, d) {
|
|
1104
|
-
t /= d / 2;
|
|
1105
|
-
if (t < 1) return (c / 2) * t * t * t * t * t + b;
|
|
1106
|
-
t -= 2;
|
|
1107
|
-
return (c / 2) * (t * t * t * t * t + 2) + b;
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
requestAnimationFrame(animation);
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
function switchDialect(key) {
|
|
1114
|
-
const data = dialects[key];
|
|
1115
|
-
|
|
1116
|
-
// Update UI Text
|
|
1117
|
-
document.getElementById("dialect-title").innerText = data.title;
|
|
1118
|
-
document.getElementById("dialect-desc").innerHTML = data.desc.replace(
|
|
1119
|
-
"prova",
|
|
1120
|
-
"<strong>prova</strong>"
|
|
1121
|
-
);
|
|
1122
|
-
document.getElementById("dialect-badge").innerText =
|
|
1123
|
-
key === "math"
|
|
1124
|
-
? "Lógica Formal"
|
|
1125
|
-
: key === "narrative"
|
|
1126
|
-
? "Storytelling (BDD)"
|
|
1127
|
-
: "Engenharia de Sistemas";
|
|
1128
|
-
document.getElementById(
|
|
1129
|
-
"dialect-badge"
|
|
1130
|
-
).className = `inline-block px-3 py-1 rounded text-xs font-bold mb-4 bg-${data.theme}-100 text-${data.theme}-800`;
|
|
1131
|
-
|
|
1132
|
-
// Update Keywords
|
|
1133
|
-
const kwList = document.getElementById("dialect-keywords");
|
|
1134
|
-
kwList.innerHTML = `
|
|
1135
|
-
<li class="flex items-center gap-2"><span class="text-${
|
|
1136
|
-
data.theme
|
|
1137
|
-
}-500">➤</span> ${data.keywords.join(", ")}</li>
|
|
1138
|
-
<li class="flex items-center gap-2 text-slate-400 text-xs">A escolha semântica altera a percepção do teste.</li>
|
|
1139
|
-
`;
|
|
1140
|
-
|
|
1141
|
-
// Update Code
|
|
1142
|
-
document.getElementById("dialect-code").innerText = data.code;
|
|
1143
|
-
document.getElementById(
|
|
1144
|
-
"dialect-code"
|
|
1145
|
-
).className = `font-mono text-sm overflow-x-auto code-scroll text-${data.theme}-300`;
|
|
1146
|
-
|
|
1147
|
-
// Update Tabs Styling
|
|
1148
|
-
document.querySelectorAll(".tab-btn").forEach((btn) => {
|
|
1149
|
-
btn.className =
|
|
1150
|
-
"tab-btn px-6 py-3 text-sm font-medium text-slate-500 hover:text-slate-700 focus:outline-none whitespace-nowrap border-b-2 border-transparent";
|
|
1151
|
-
});
|
|
1152
|
-
const activeTab = document.getElementById(`tab-${key}`);
|
|
1153
|
-
activeTab.className = `tab-btn px-6 py-3 text-sm font-medium whitespace-nowrap border-b-2 border-${data.theme}-600 text-${data.theme}-600 font-bold tab-active`;
|
|
1154
|
-
|
|
1155
|
-
// Update Chart
|
|
1156
|
-
updateSuitabilityChart(data.radarData, data.theme, data.title);
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
function morphCode(key) {
|
|
1160
|
-
const data = dialects[key];
|
|
1161
|
-
const display = document.getElementById("morph-display");
|
|
1162
|
-
const label = document.getElementById("morph-label");
|
|
1163
|
-
|
|
1164
|
-
// Fade out
|
|
1165
|
-
display.style.opacity = "0";
|
|
1166
|
-
|
|
1167
|
-
setTimeout(() => {
|
|
1168
|
-
display.innerText = data.code;
|
|
1169
|
-
label.innerText = `CODE: ${data.name.toUpperCase()}`;
|
|
1170
|
-
|
|
1171
|
-
// Color mapping for the dark theme block
|
|
1172
|
-
const colorMap = {
|
|
1173
|
-
math: "text-indigo-300",
|
|
1174
|
-
narrative: "text-emerald-300",
|
|
1175
|
-
imperative: "text-amber-300",
|
|
1176
|
-
};
|
|
1177
|
-
display.className = `font-mono text-sm leading-relaxed overflow-x-auto transition-opacity duration-300 ${colorMap[key]}`;
|
|
1178
|
-
|
|
1179
|
-
// Fade in
|
|
1180
|
-
display.style.opacity = "1";
|
|
1181
|
-
}, 300);
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
function renderRosettaTable(category) {
|
|
1185
|
-
const tbody = document.getElementById("rosettaBody");
|
|
1186
|
-
tbody.innerHTML = "";
|
|
1187
|
-
|
|
1188
|
-
const filtered =
|
|
1189
|
-
category === "all"
|
|
1190
|
-
? rosettaData
|
|
1191
|
-
: rosettaData.filter((d) => d.cat === category);
|
|
1192
|
-
|
|
1193
|
-
filtered.forEach((row) => {
|
|
1194
|
-
const tr = document.createElement("tr");
|
|
1195
|
-
tr.className = "hover:bg-slate-50 transition-colors";
|
|
1196
|
-
tr.innerHTML = `
|
|
1197
|
-
<td class="px-6 py-4 font-bold text-xs text-slate-400 uppercase">${row.cat}</td>
|
|
1198
|
-
<td class="px-6 py-4 font-semibold text-slate-800 bg-slate-50 border-r border-slate-100">${row.jest}</td>
|
|
1199
|
-
<td class="px-6 py-4 text-indigo-700 font-medium">${row.math}</td>
|
|
1200
|
-
<td class="px-6 py-4 text-emerald-700 font-medium">${row.narr}</td>
|
|
1201
|
-
<td class="px-6 py-4 text-amber-700 font-medium">${row.imp}</td>
|
|
1202
|
-
`;
|
|
1203
|
-
tbody.appendChild(tr);
|
|
1204
|
-
});
|
|
1205
|
-
}
|
|
1206
|
-
|
|
1207
|
-
function filterTable() {
|
|
1208
|
-
const select = document.getElementById("categoryFilter");
|
|
1209
|
-
renderRosettaTable(select.value);
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
// --- CHARTS IMPLEMENTATION ---
|
|
1213
|
-
|
|
1214
|
-
function initCharts() {
|
|
1215
|
-
// 1. Suitability Radar Chart
|
|
1216
|
-
const ctx1 = document
|
|
1217
|
-
.getElementById("suitabilityChart")
|
|
1218
|
-
.getContext("2d");
|
|
1219
|
-
currentChart = new Chart(ctx1, {
|
|
1220
|
-
type: "radar",
|
|
1221
|
-
data: {
|
|
1222
|
-
labels: [
|
|
1223
|
-
"Lógica Pura",
|
|
1224
|
-
"UI/UX",
|
|
1225
|
-
"API/Backend",
|
|
1226
|
-
"Documentação",
|
|
1227
|
-
"Compliance",
|
|
1228
|
-
],
|
|
1229
|
-
datasets: [
|
|
1230
|
-
{
|
|
1231
|
-
label: "O Matemático",
|
|
1232
|
-
data: dialects.math.radarData,
|
|
1233
|
-
fill: true,
|
|
1234
|
-
backgroundColor: "rgba(79, 70, 229, 0.2)",
|
|
1235
|
-
borderColor: "rgb(79, 70, 229)",
|
|
1236
|
-
pointBackgroundColor: "rgb(79, 70, 229)",
|
|
1237
|
-
pointBorderColor: "#fff",
|
|
1238
|
-
pointHoverBackgroundColor: "#fff",
|
|
1239
|
-
pointHoverBorderColor: "rgb(79, 70, 229)",
|
|
1240
|
-
},
|
|
1241
|
-
],
|
|
1242
|
-
},
|
|
1243
|
-
options: {
|
|
1244
|
-
maintainAspectRatio: false,
|
|
1245
|
-
responsive: true,
|
|
1246
|
-
elements: { line: { tension: 0.3 } },
|
|
1247
|
-
scales: {
|
|
1248
|
-
r: {
|
|
1249
|
-
angleLines: { color: "#e2e8f0" },
|
|
1250
|
-
grid: { color: "#e2e8f0" },
|
|
1251
|
-
pointLabels: {
|
|
1252
|
-
font: { size: 10, family: "Inter" },
|
|
1253
|
-
color: "#64748b",
|
|
1254
|
-
},
|
|
1255
|
-
ticks: { display: false, max: 100, min: 0 },
|
|
1256
|
-
},
|
|
1257
|
-
},
|
|
1258
|
-
plugins: {
|
|
1259
|
-
legend: { display: false },
|
|
1260
|
-
tooltip: { enabled: true },
|
|
1261
|
-
},
|
|
1262
|
-
},
|
|
1263
|
-
});
|
|
1264
|
-
|
|
1265
|
-
// 2. API Distribution Bar Chart
|
|
1266
|
-
const counts = {
|
|
1267
|
-
Structure: rosettaData.filter((x) => x.cat === "Estrutura").length,
|
|
1268
|
-
Assertion: rosettaData.filter((x) => x.cat === "Asserção").length,
|
|
1269
|
-
Mocks: rosettaData.filter((x) => x.cat === "Mocks").length,
|
|
1270
|
-
Lifecycle: rosettaData.filter((x) => x.cat === "Lifecycle").length,
|
|
1271
|
-
};
|
|
1272
|
-
|
|
1273
|
-
const ctx2 = document
|
|
1274
|
-
.getElementById("distributionChart")
|
|
1275
|
-
.getContext("2d");
|
|
1276
|
-
distributionChart = new Chart(ctx2, {
|
|
1277
|
-
type: "bar",
|
|
1278
|
-
data: {
|
|
1279
|
-
labels: Object.keys(counts),
|
|
1280
|
-
datasets: [
|
|
1281
|
-
{
|
|
1282
|
-
label: "Funções da API",
|
|
1283
|
-
data: Object.values(counts),
|
|
1284
|
-
backgroundColor: [
|
|
1285
|
-
"rgba(148, 163, 184, 0.7)",
|
|
1286
|
-
"rgba(148, 163, 184, 0.7)",
|
|
1287
|
-
"rgba(71, 85, 105, 0.9)", // Emphasize Mocks are heavy
|
|
1288
|
-
"rgba(148, 163, 184, 0.7)",
|
|
1289
|
-
],
|
|
1290
|
-
borderRadius: 6,
|
|
1291
|
-
},
|
|
1292
|
-
],
|
|
1293
|
-
},
|
|
1294
|
-
options: {
|
|
1295
|
-
maintainAspectRatio: false,
|
|
1296
|
-
responsive: true,
|
|
1297
|
-
plugins: {
|
|
1298
|
-
legend: { display: false },
|
|
1299
|
-
tooltip: {
|
|
1300
|
-
callbacks: {
|
|
1301
|
-
title: (context) => `Categoria: ${context[0].label}`,
|
|
1302
|
-
label: (context) => `${context.raw} Funções Mapeadas`,
|
|
1303
|
-
},
|
|
1304
|
-
},
|
|
1305
|
-
},
|
|
1306
|
-
scales: {
|
|
1307
|
-
y: {
|
|
1308
|
-
beginAtZero: true,
|
|
1309
|
-
grid: { display: false },
|
|
1310
|
-
},
|
|
1311
|
-
x: {
|
|
1312
|
-
grid: { display: false },
|
|
1313
|
-
},
|
|
1314
|
-
},
|
|
1315
|
-
},
|
|
1316
|
-
});
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
function updateSuitabilityChart(data, theme, label) {
|
|
1320
|
-
if (!currentChart) return;
|
|
1321
|
-
|
|
1322
|
-
const colors = {
|
|
1323
|
-
indigo: { bg: "rgba(79, 70, 229, 0.2)", border: "rgb(79, 70, 229)" },
|
|
1324
|
-
emerald: {
|
|
1325
|
-
bg: "rgba(16, 185, 129, 0.2)",
|
|
1326
|
-
border: "rgb(16, 185, 129)",
|
|
1327
|
-
},
|
|
1328
|
-
amber: { bg: "rgba(245, 158, 11, 0.2)", border: "rgb(245, 158, 11)" },
|
|
1329
|
-
};
|
|
1330
|
-
|
|
1331
|
-
currentChart.data.datasets[0].data = data;
|
|
1332
|
-
currentChart.data.datasets[0].label = label;
|
|
1333
|
-
currentChart.data.datasets[0].backgroundColor = colors[theme].bg;
|
|
1334
|
-
currentChart.data.datasets[0].borderColor = colors[theme].border;
|
|
1335
|
-
currentChart.data.datasets[0].pointBackgroundColor =
|
|
1336
|
-
colors[theme].border;
|
|
1337
|
-
currentChart.data.datasets[0].pointHoverBorderColor =
|
|
1338
|
-
colors[theme].border;
|
|
1339
|
-
|
|
1340
|
-
currentChart.update();
|
|
1341
|
-
}
|
|
1342
|
-
</script>
|
|
1343
|
-
</body>
|
|
1344
|
-
</html>
|