@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.
Files changed (96) hide show
  1. package/dist/examples/imperative.spec.d.ts +1 -0
  2. package/dist/examples/imperative.spec.js +46 -0
  3. package/dist/examples/math.spec.d.ts +1 -0
  4. package/dist/examples/math.spec.js +39 -0
  5. package/dist/examples/narrative.spec.d.ts +1 -0
  6. package/dist/examples/narrative.spec.js +47 -0
  7. package/dist/examples/polyglot-shopping-cart.spec.d.ts +11 -0
  8. package/dist/examples/polyglot-shopping-cart.spec.js +161 -0
  9. package/dist/examples/sanity.spec.d.ts +1 -0
  10. package/dist/examples/sanity.spec.js +39 -0
  11. package/dist/examples/showcase-api.spec.d.ts +1 -0
  12. package/dist/examples/showcase-api.spec.js +62 -0
  13. package/dist/examples/test-api.d.ts +1 -0
  14. package/dist/examples/test-api.js +32 -0
  15. package/dist/packages/api-test-dialect/index.d.ts +28 -0
  16. package/dist/packages/api-test-dialect/index.js +102 -0
  17. package/dist/packages/reqify/index.d.ts +12 -0
  18. package/dist/packages/reqify/index.js +24 -0
  19. package/dist/src/cli.d.ts +6 -0
  20. package/dist/src/cli.js +330 -0
  21. package/dist/src/index.d.ts +134 -0
  22. package/dist/src/index.js +374 -0
  23. package/dist/src/semantic/core.d.ts +24 -0
  24. package/dist/src/semantic/core.js +16 -0
  25. package/{types/api-types.ts → dist/types/api-types.d.ts} +6 -11
  26. package/dist/types/api-types.js +1 -0
  27. package/package.json +59 -35
  28. package/packages/api-test-dialect/index.ts +132 -132
  29. package/readme.md +58 -58
  30. package/src/cli.ts +1 -1
  31. package/src/index.ts +19 -16
  32. package/src/semantic/core.ts +26 -0
  33. package/CHANGELOG.md +0 -73
  34. package/bun.lock +0 -22
  35. package/bunfig.toml +0 -2
  36. package/critica.md +0 -77
  37. package/docs/4-ideias.md +0 -66
  38. package/docs/api-api.md +0 -93
  39. package/docs/api-imperativo.md +0 -125
  40. package/docs/api-matematico.md +0 -145
  41. package/docs/api-narrativo.md +0 -181
  42. package/docs/guia-rapido.md +0 -189
  43. package/docs/whitepaper.md +0 -21
  44. package/examples/imperative.spec.ts +0 -58
  45. package/examples/math.spec.ts +0 -52
  46. package/examples/narrative.spec.ts +0 -61
  47. package/examples/polyglot-shopping-cart.spec.ts +0 -212
  48. package/examples/sanity.spec.ts +0 -54
  49. package/examples/showcase-api.spec.ts +0 -70
  50. package/examples/test-api.ts +0 -36
  51. package/infograficos/detalhado.png +0 -0
  52. package/infograficos/mobile.png +0 -0
  53. package/infograficos/normal.png +0 -0
  54. package/landing-page/README.md +0 -38
  55. package/landing-page/bun.lock +0 -609
  56. package/landing-page/eslint.config.js +0 -23
  57. package/landing-page/index.html +0 -17
  58. package/landing-page/package-lock.json +0 -2962
  59. package/landing-page/package.json +0 -34
  60. package/landing-page/postcss.config.js +0 -6
  61. package/landing-page/public/vite.svg +0 -1
  62. package/landing-page/src/App.tsx +0 -358
  63. package/landing-page/src/assets/react.svg +0 -1
  64. package/landing-page/src/index.css +0 -34
  65. package/landing-page/src/main.tsx +0 -10
  66. package/landing-page/tailwind.config.js +0 -59
  67. package/landing-page/tsconfig.app.json +0 -28
  68. package/landing-page/tsconfig.json +0 -7
  69. package/landing-page/tsconfig.node.json +0 -26
  70. package/landing-page/vite.config.ts +0 -7
  71. package/logo.png +0 -0
  72. package/output.log +0 -60
  73. package/podcast/O_Matem/303/241tico,_o_Narrador_e_o_Engenheiro.json +0 -0
  74. package/podcast/O_Matem/303/241tico,_o_Narrador_e_o_Engenheiro.md +0 -0
  75. package/podcast/critica-Dialetos_de_teste__inova/303/247/303/243o_ou_fragmenta/303/247/303/243o_.json +0 -0
  76. package/podcast/critica-Dialetos_de_teste__inova/303/247/303/243o_ou_fragmenta/303/247/303/243o_.md +0 -0
  77. package/podcast/critica-Unificar_filosofia_e_pr/303/241tica_na_documenta/303/247/303/243o_(7_words__covers_t.md +0 -1
  78. package/podcast/critica-Unificar_filosofia_e_pr/303/241tica_na_documenta/303/247/303/243o__7_words__covers_t.ogg +0 -0
  79. package/podcast/critica2-Sil/303/252ncio_estrat/303/251gico_e_sobrecarga_em_READMEs.ogg +0 -0
  80. package/podcast/critica2.json +0 -3191
  81. package/podcast/critica2.md +0 -1
  82. package/podcast/debate-Dialetos_de_teste__inova/303/247/303/243o_ou_fragmenta/303/247/303/243o_.json +0 -0
  83. package/podcast/debate-Dialetos_de_teste__inova/303/247/303/243o_ou_fragmenta/303/247/303/243o_.md +0 -0
  84. package/reports/01-01-2026_00-45.md +0 -40
  85. package/reports/01-01-2026_02-30.md +0 -37
  86. package/reports/03-02-2026_10-55.md +0 -8
  87. package/reports/03-02-2026_11-45.md +0 -13
  88. package/reports/03-02-2026_11-50.md +0 -10
  89. package/reports/26-01-2026_16-25.md +0 -31
  90. package/reports/26-01-2026_19-20.md +0 -27
  91. package/reports/31-12-2025_22-35.md +0 -25
  92. package/reports/31-12-2025_22-45.md +0 -15
  93. package/slides/Dialetos_de_Teste_Um_Executor_M/303/272ltiplos_Vocabul/303/241rios.pdf +0 -0
  94. package/tabela.html +0 -350
  95. package/tsconfig.json +0 -22
  96. 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>