@acutis/cli 0.1.2-dev.21 → 0.1.2-dev.22

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 (133) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/1DjC7bBa.js +64 -0
  3. package/.output/public/_nuxt/BNJ2GN0A.js +1 -0
  4. package/.output/public/_nuxt/{b5tj-z25.js → BgV7uYhh.js} +1 -1
  5. package/.output/public/_nuxt/C0IyPp1C.js +28 -0
  6. package/.output/public/_nuxt/C5NzO9dO.js +1 -0
  7. package/.output/public/_nuxt/CUTaKHid.js +1 -0
  8. package/.output/public/_nuxt/DHNHaKIX.js +1 -0
  9. package/.output/public/_nuxt/DKFReY2j.js +1 -0
  10. package/.output/public/_nuxt/DXk74b-E.js +1 -0
  11. package/.output/public/_nuxt/Dc6npEU3.js +1 -0
  12. package/.output/public/_nuxt/DyrXGv84.js +1 -0
  13. package/.output/public/_nuxt/WurCawTj.js +3 -0
  14. package/.output/public/_nuxt/builds/latest.json +1 -1
  15. package/.output/public/_nuxt/builds/meta/f4520b8a-9c39-4e41-af7a-b806928ef3ac.json +1 -0
  16. package/.output/public/_nuxt/lH5PYs8w.js +1 -0
  17. package/.output/public/_nuxt/tags.C6gBUbEB.css +1 -0
  18. package/.output/public/_nuxt/zH54s-gB.js +6 -0
  19. package/.output/server/chunks/_/project.service.mjs +1 -1
  20. package/.output/server/chunks/build/{Pagination-D2AcUggP.mjs → Pagination-BuiQpYWD.mjs} +26 -26
  21. package/.output/server/chunks/build/{Pagination-D2AcUggP.mjs.map → Pagination-BuiQpYWD.mjs.map} +1 -1
  22. package/.output/server/chunks/build/{_...scenario_-D8fF8UCa.mjs → _...scenario_-PVjOOR8j.mjs} +606 -211
  23. package/.output/server/chunks/build/_...scenario_-PVjOOR8j.mjs.map +1 -0
  24. package/.output/server/chunks/build/{_slug_-0Xu9aQ3b.mjs → _slug_-COpWNGAB.mjs} +745 -416
  25. package/.output/server/chunks/build/_slug_-COpWNGAB.mjs.map +1 -0
  26. package/.output/server/chunks/build/{origin-_7Gia2Vr.mjs → origin-NWHPNXep.mjs} +594 -20
  27. package/.output/server/chunks/build/origin-NWHPNXep.mjs.map +1 -0
  28. package/.output/server/chunks/build/{pages-C0ubizZ3.mjs → pages-C7-vXRcH.mjs} +22 -25
  29. package/.output/server/chunks/build/{pages-C0ubizZ3.mjs.map → pages-C7-vXRcH.mjs.map} +1 -1
  30. package/.output/server/chunks/build/tags-X7K7nkM2.mjs +2079 -0
  31. package/.output/server/chunks/build/tags-X7K7nkM2.mjs.map +1 -0
  32. package/.output/server/chunks/nitro/nitro.mjs +142 -363
  33. package/.output/server/chunks/routes/renderer.mjs +2 -2
  34. package/.output/server/chunks/virtual/entry.mjs +29334 -29367
  35. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  36. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  37. package/.output/server/package.json +1 -1
  38. package/package.json +1 -1
  39. package/.output/public/_nuxt/9eLkUDDj.js +0 -1
  40. package/.output/public/_nuxt/ANcp5QFz.js +0 -1
  41. package/.output/public/_nuxt/BEQgcp5R.js +0 -1
  42. package/.output/public/_nuxt/BEk00u4_.js +0 -1
  43. package/.output/public/_nuxt/BGdmRvCK2.js +0 -8
  44. package/.output/public/_nuxt/BGkBW2ni2.js +0 -1
  45. package/.output/public/_nuxt/BKydt2Wp2.js +0 -4
  46. package/.output/public/_nuxt/BMLYuU_e.js +0 -1
  47. package/.output/public/_nuxt/BWJpSLJL.js +0 -1
  48. package/.output/public/_nuxt/BXpPYfMx.js +0 -1
  49. package/.output/public/_nuxt/BbjTtCyI.js +0 -3
  50. package/.output/public/_nuxt/Bd538XcA2.js +0 -1
  51. package/.output/public/_nuxt/Bp3A7I5W2.js +0 -1
  52. package/.output/public/_nuxt/BuOb9NX0.js +0 -1
  53. package/.output/public/_nuxt/C1tNhfTr.js +0 -1
  54. package/.output/public/_nuxt/C2KIeuhG.js +0 -1
  55. package/.output/public/_nuxt/C5uJN_MU.js +0 -1
  56. package/.output/public/_nuxt/CBVnImq2.js +0 -1
  57. package/.output/public/_nuxt/CDI0GNVb2.js +0 -1
  58. package/.output/public/_nuxt/CIFC2HNk.js +0 -1
  59. package/.output/public/_nuxt/CKps1Vc12.js +0 -3
  60. package/.output/public/_nuxt/CRH0iqnQ.js +0 -1
  61. package/.output/public/_nuxt/CTqLwyQP.js +0 -1
  62. package/.output/public/_nuxt/CU7sPrmY.js +0 -3
  63. package/.output/public/_nuxt/CfOqJVtU.js +0 -1
  64. package/.output/public/_nuxt/Ch1EeKHP.js +0 -1
  65. package/.output/public/_nuxt/Clv7nJ_T2.js +0 -1
  66. package/.output/public/_nuxt/CqZ7dV6a2.js +0 -64
  67. package/.output/public/_nuxt/D-7v7DZs.js +0 -1
  68. package/.output/public/_nuxt/DEJ3sRrh2.js +0 -1
  69. package/.output/public/_nuxt/DPM_BYFz2.js +0 -1
  70. package/.output/public/_nuxt/DQk6DVe-.js +0 -28
  71. package/.output/public/_nuxt/DXLPf3t6.js +0 -1
  72. package/.output/public/_nuxt/DtuQPKVG.js +0 -1
  73. package/.output/public/_nuxt/FvWrDx_z.js +0 -1
  74. package/.output/public/_nuxt/Gcazu-lR.js +0 -1
  75. package/.output/public/_nuxt/QcKfgokC.js +0 -1
  76. package/.output/public/_nuxt/XDsaI4JL.js +0 -1
  77. package/.output/public/_nuxt/builds/meta/b5eccb33-8028-439b-99f5-6377d84bdfed.json +0 -1
  78. package/.output/public/_nuxt/dCqlxK8U2.js +0 -1
  79. package/.output/public/_nuxt/f0o80Gcm.js +0 -1
  80. package/.output/public/_nuxt/k5q7GKnv.js +0 -1
  81. package/.output/public/_nuxt/modal.3A_G7d4A.css +0 -1
  82. package/.output/public/_nuxt/tLr-SJaf.js +0 -1
  83. package/.output/public/_nuxt/tags.B5A43CvD.css +0 -1
  84. package/.output/public/dev/sample-run.webm +0 -0
  85. package/.output/server/chunks/build/Alert-DX-UEOEY.mjs +0 -433
  86. package/.output/server/chunks/build/Alert-DX-UEOEY.mjs.map +0 -1
  87. package/.output/server/chunks/build/Badge-DCotJtd8.mjs +0 -394
  88. package/.output/server/chunks/build/Badge-DCotJtd8.mjs.map +0 -1
  89. package/.output/server/chunks/build/Card-D7QwltkF.mjs +0 -144
  90. package/.output/server/chunks/build/Card-D7QwltkF.mjs.map +0 -1
  91. package/.output/server/chunks/build/Container-Biz72Lxy.mjs +0 -55
  92. package/.output/server/chunks/build/Container-Biz72Lxy.mjs.map +0 -1
  93. package/.output/server/chunks/build/_...scenario_-D8fF8UCa.mjs.map +0 -1
  94. package/.output/server/chunks/build/_slug_-0Xu9aQ3b.mjs.map +0 -1
  95. package/.output/server/chunks/build/auth-status-kUEDoxDI.mjs +0 -53
  96. package/.output/server/chunks/build/auth-status-kUEDoxDI.mjs.map +0 -1
  97. package/.output/server/chunks/build/auth-status-kswM9iTW.mjs +0 -128
  98. package/.output/server/chunks/build/auth-status-kswM9iTW.mjs.map +0 -1
  99. package/.output/server/chunks/build/empty-D8gbt7LG.mjs +0 -44
  100. package/.output/server/chunks/build/empty-D8gbt7LG.mjs.map +0 -1
  101. package/.output/server/chunks/build/generation-warnings-D4Br9kVN.mjs +0 -123
  102. package/.output/server/chunks/build/generation-warnings-D4Br9kVN.mjs.map +0 -1
  103. package/.output/server/chunks/build/history-eVF-ijkS.mjs +0 -163
  104. package/.output/server/chunks/build/history-eVF-ijkS.mjs.map +0 -1
  105. package/.output/server/chunks/build/modal-CELo8GdZ.mjs +0 -342
  106. package/.output/server/chunks/build/modal-CELo8GdZ.mjs.map +0 -1
  107. package/.output/server/chunks/build/modal-CUNv4bFw.mjs +0 -659
  108. package/.output/server/chunks/build/modal-CUNv4bFw.mjs.map +0 -1
  109. package/.output/server/chunks/build/modal-Cl4zRASg.mjs +0 -321
  110. package/.output/server/chunks/build/modal-Cl4zRASg.mjs.map +0 -1
  111. package/.output/server/chunks/build/origin-_7Gia2Vr.mjs.map +0 -1
  112. package/.output/server/chunks/build/phrases-rvaRKDG_.mjs +0 -38
  113. package/.output/server/chunks/build/phrases-rvaRKDG_.mjs.map +0 -1
  114. package/.output/server/chunks/build/project-run-filtered-DFIlti8u.mjs +0 -455
  115. package/.output/server/chunks/build/project-run-filtered-DFIlti8u.mjs.map +0 -1
  116. package/.output/server/chunks/build/run-stream-CNVDpZ_S.mjs +0 -157
  117. package/.output/server/chunks/build/run-stream-CNVDpZ_S.mjs.map +0 -1
  118. package/.output/server/chunks/build/scenario-runs-bilf1StX.mjs +0 -135
  119. package/.output/server/chunks/build/scenario-runs-bilf1StX.mjs.map +0 -1
  120. package/.output/server/chunks/build/scenario-suggestions-CMPsmNXz.mjs +0 -210
  121. package/.output/server/chunks/build/scenario-suggestions-CMPsmNXz.mjs.map +0 -1
  122. package/.output/server/chunks/build/scenario-test-run-DIjyHDe-.mjs +0 -505
  123. package/.output/server/chunks/build/scenario-test-run-DIjyHDe-.mjs.map +0 -1
  124. package/.output/server/chunks/build/steps-DBViokqd.mjs +0 -54
  125. package/.output/server/chunks/build/steps-DBViokqd.mjs.map +0 -1
  126. package/.output/server/chunks/build/tags-BiGRnEfK.mjs +0 -639
  127. package/.output/server/chunks/build/tags-BiGRnEfK.mjs.map +0 -1
  128. package/.output/server/chunks/build/warnings-BjFCNgyv.mjs +0 -76
  129. package/.output/server/chunks/build/warnings-BjFCNgyv.mjs.map +0 -1
  130. package/.output/server/chunks/raw/sample-run.mjs +0 -7
  131. package/.output/server/chunks/raw/sample-run.mjs.map +0 -1
  132. package/dist-ui/dev/sample-run.webm +0 -0
  133. /package/.output/public/_nuxt/{BDNMzG2s2.js → BDNMzG2s.js} +0 -0
@@ -0,0 +1,2079 @@
1
+ import { L as useState, k as useComponentProps, K as useLocale, l as useAppConfig, t as tv, P as Primitive, q as _sfc_main$6, f as _sfc_main$8, d as _sfc_main$3, u as useRoute, i as icon_default, m as modal_default$2, b as useAi, _ as _sfc_main$7, A as AI_OFF_HINT, M as useRequestEvent, $ as $fetch$2, e as extractServerError, j as _sfc_main$1$1, g as _sfc_main$4 } from '../virtual/entry.mjs';
2
+ import { b as _sfc_main$1, a as _sfc_main$2 } from './origin-NWHPNXep.mjs';
3
+ import { _ as _plugin_vue_export_helper_default } from './_plugin-vue_export-helper-BOaGB7Aw.mjs';
4
+ import { ref, computed, useSlots, unref, mergeProps, withCtx, renderSlot, openBlock, createBlock, createCommentVNode, createVNode, createTextVNode, toDisplayString, Fragment, renderList, defineComponent, isRef, useModel, h, watch, nextTick, mergeModels, createSlots, useSSRContext } from 'vue';
5
+ import { m as getRequestURL } from '../nitro/nitro.mjs';
6
+ import { ssrRenderComponent, ssrRenderSlot, ssrRenderClass, ssrInterpolate, ssrRenderList, ssrRenderAttrs, ssrRenderAttr, ssrIncludeBooleanAttr } from 'vue/server-renderer';
7
+ import Prism from 'prismjs';
8
+
9
+ //#region virtual:nuxt:node_modules%2F.cache%2Fnuxt%2F.nuxt%2Fui%2Falert.ts
10
+ var virtual_nuxt_node_modules_2F_cache_2Fnuxt_2F_nuxt_2Fui_2Falert_default = {
11
+ "slots": {
12
+ "root": "relative overflow-hidden w-full rounded-lg p-4 flex gap-2.5",
13
+ "wrapper": "min-w-0 flex-1 flex flex-col",
14
+ "title": "text-sm font-medium",
15
+ "description": "text-sm opacity-90",
16
+ "icon": "shrink-0 size-5",
17
+ "avatar": "shrink-0",
18
+ "avatarSize": "2xl",
19
+ "actions": "flex flex-wrap gap-1.5 shrink-0",
20
+ "close": "p-0"
21
+ },
22
+ "variants": {
23
+ "color": {
24
+ "primary": "",
25
+ "secondary": "",
26
+ "success": "",
27
+ "info": "",
28
+ "warning": "",
29
+ "error": "",
30
+ "neutral": ""
31
+ },
32
+ "variant": {
33
+ "solid": "",
34
+ "outline": "",
35
+ "soft": "",
36
+ "subtle": ""
37
+ },
38
+ "orientation": {
39
+ "horizontal": {
40
+ "root": "items-center",
41
+ "actions": "items-center"
42
+ },
43
+ "vertical": {
44
+ "root": "items-start",
45
+ "actions": "items-start mt-2.5"
46
+ }
47
+ },
48
+ "title": { "true": { "description": "mt-1" } }
49
+ },
50
+ "compoundVariants": [
51
+ {
52
+ "color": "primary",
53
+ "variant": "solid",
54
+ "class": { "root": "bg-primary text-inverted" }
55
+ },
56
+ {
57
+ "color": "secondary",
58
+ "variant": "solid",
59
+ "class": { "root": "bg-secondary text-inverted" }
60
+ },
61
+ {
62
+ "color": "success",
63
+ "variant": "solid",
64
+ "class": { "root": "bg-success text-inverted" }
65
+ },
66
+ {
67
+ "color": "info",
68
+ "variant": "solid",
69
+ "class": { "root": "bg-info text-inverted" }
70
+ },
71
+ {
72
+ "color": "warning",
73
+ "variant": "solid",
74
+ "class": { "root": "bg-warning text-inverted" }
75
+ },
76
+ {
77
+ "color": "error",
78
+ "variant": "solid",
79
+ "class": { "root": "bg-error text-inverted" }
80
+ },
81
+ {
82
+ "color": "primary",
83
+ "variant": "outline",
84
+ "class": { "root": "text-primary ring ring-inset ring-primary/25" }
85
+ },
86
+ {
87
+ "color": "secondary",
88
+ "variant": "outline",
89
+ "class": { "root": "text-secondary ring ring-inset ring-secondary/25" }
90
+ },
91
+ {
92
+ "color": "success",
93
+ "variant": "outline",
94
+ "class": { "root": "text-success ring ring-inset ring-success/25" }
95
+ },
96
+ {
97
+ "color": "info",
98
+ "variant": "outline",
99
+ "class": { "root": "text-info ring ring-inset ring-info/25" }
100
+ },
101
+ {
102
+ "color": "warning",
103
+ "variant": "outline",
104
+ "class": { "root": "text-warning ring ring-inset ring-warning/25" }
105
+ },
106
+ {
107
+ "color": "error",
108
+ "variant": "outline",
109
+ "class": { "root": "text-error ring ring-inset ring-error/25" }
110
+ },
111
+ {
112
+ "color": "primary",
113
+ "variant": "soft",
114
+ "class": { "root": "bg-primary/10 text-primary" }
115
+ },
116
+ {
117
+ "color": "secondary",
118
+ "variant": "soft",
119
+ "class": { "root": "bg-secondary/10 text-secondary" }
120
+ },
121
+ {
122
+ "color": "success",
123
+ "variant": "soft",
124
+ "class": { "root": "bg-success/10 text-success" }
125
+ },
126
+ {
127
+ "color": "info",
128
+ "variant": "soft",
129
+ "class": { "root": "bg-info/10 text-info" }
130
+ },
131
+ {
132
+ "color": "warning",
133
+ "variant": "soft",
134
+ "class": { "root": "bg-warning/10 text-warning" }
135
+ },
136
+ {
137
+ "color": "error",
138
+ "variant": "soft",
139
+ "class": { "root": "bg-error/10 text-error" }
140
+ },
141
+ {
142
+ "color": "primary",
143
+ "variant": "subtle",
144
+ "class": { "root": "bg-primary/10 text-primary ring ring-inset ring-primary/25" }
145
+ },
146
+ {
147
+ "color": "secondary",
148
+ "variant": "subtle",
149
+ "class": { "root": "bg-secondary/10 text-secondary ring ring-inset ring-secondary/25" }
150
+ },
151
+ {
152
+ "color": "success",
153
+ "variant": "subtle",
154
+ "class": { "root": "bg-success/10 text-success ring ring-inset ring-success/25" }
155
+ },
156
+ {
157
+ "color": "info",
158
+ "variant": "subtle",
159
+ "class": { "root": "bg-info/10 text-info ring ring-inset ring-info/25" }
160
+ },
161
+ {
162
+ "color": "warning",
163
+ "variant": "subtle",
164
+ "class": { "root": "bg-warning/10 text-warning ring ring-inset ring-warning/25" }
165
+ },
166
+ {
167
+ "color": "error",
168
+ "variant": "subtle",
169
+ "class": { "root": "bg-error/10 text-error ring ring-inset ring-error/25" }
170
+ },
171
+ {
172
+ "color": "neutral",
173
+ "variant": "solid",
174
+ "class": { "root": "text-inverted bg-inverted" }
175
+ },
176
+ {
177
+ "color": "neutral",
178
+ "variant": "outline",
179
+ "class": { "root": "text-highlighted bg-default ring ring-inset ring-default" }
180
+ },
181
+ {
182
+ "color": "neutral",
183
+ "variant": "soft",
184
+ "class": { "root": "text-highlighted bg-elevated/50" }
185
+ },
186
+ {
187
+ "color": "neutral",
188
+ "variant": "subtle",
189
+ "class": { "root": "text-highlighted bg-elevated/50 ring ring-inset ring-accented" }
190
+ }
191
+ ],
192
+ "defaultVariants": {
193
+ "color": "primary",
194
+ "variant": "solid"
195
+ }
196
+ };
197
+ //#endregion
198
+ //#region node_modules/.pnpm/@nuxt+ui@4.10.0_e9e3fcf18fb997bdd8dc5f7c218a2205/node_modules/@nuxt/ui/dist/runtime/components/Alert.vue
199
+ var _sfc_main = {
200
+ __name: "UAlert",
201
+ __ssrInlineRender: true,
202
+ props: {
203
+ as: {
204
+ type: null,
205
+ required: false
206
+ },
207
+ title: {
208
+ type: String,
209
+ required: false
210
+ },
211
+ description: {
212
+ type: String,
213
+ required: false
214
+ },
215
+ icon: {
216
+ type: null,
217
+ required: false
218
+ },
219
+ avatar: {
220
+ type: Object,
221
+ required: false
222
+ },
223
+ color: {
224
+ type: null,
225
+ required: false
226
+ },
227
+ variant: {
228
+ type: null,
229
+ required: false
230
+ },
231
+ orientation: {
232
+ type: null,
233
+ required: false,
234
+ default: "vertical"
235
+ },
236
+ actions: {
237
+ type: Array,
238
+ required: false
239
+ },
240
+ close: {
241
+ type: [Boolean, Object],
242
+ required: false
243
+ },
244
+ closeIcon: {
245
+ type: null,
246
+ required: false
247
+ },
248
+ class: {
249
+ type: null,
250
+ required: false
251
+ },
252
+ ui: {
253
+ type: Object,
254
+ required: false
255
+ }
256
+ },
257
+ emits: ["update:open"],
258
+ setup(__props, { emit: __emit }) {
259
+ const _props = __props;
260
+ const emits = __emit;
261
+ const slots = useSlots();
262
+ const props = useComponentProps("alert", _props);
263
+ const { t } = useLocale();
264
+ const appConfig = useAppConfig();
265
+ const ui = computed(() => tv({
266
+ extend: virtual_nuxt_node_modules_2F_cache_2Fnuxt_2F_nuxt_2Fui_2Falert_default,
267
+ ...appConfig.ui?.alert || {}
268
+ })({
269
+ color: props.color,
270
+ variant: props.variant,
271
+ orientation: props.orientation,
272
+ title: !!props.title || !!slots.title
273
+ }));
274
+ return (_ctx, _push, _parent, _attrs) => {
275
+ _push(ssrRenderComponent(unref(Primitive), mergeProps({
276
+ as: unref(props).as,
277
+ "data-orientation": unref(props).orientation,
278
+ "data-slot": "root",
279
+ class: ui.value.root({ class: [unref(props).ui?.root, unref(props).class] })
280
+ }, _attrs), {
281
+ default: withCtx((_, _push, _parent, _scopeId) => {
282
+ if (_push) {
283
+ ssrRenderSlot(_ctx.$slots, "leading", { ui: ui.value }, () => {
284
+ if (unref(props).avatar) _push(ssrRenderComponent(_sfc_main$6, mergeProps({ size: unref(props).ui?.avatarSize || ui.value.avatarSize() }, unref(props).avatar, {
285
+ "data-slot": "avatar",
286
+ class: ui.value.avatar({ class: unref(props).ui?.avatar })
287
+ }), null, _parent, _scopeId));
288
+ else if (unref(props).icon) _push(ssrRenderComponent(_sfc_main$8, {
289
+ name: unref(props).icon,
290
+ "data-slot": "icon",
291
+ class: ui.value.icon({ class: unref(props).ui?.icon })
292
+ }, null, _parent, _scopeId));
293
+ else _push(`<!---->`);
294
+ }, _push, _parent, _scopeId);
295
+ _push(`<div data-slot="wrapper" class="${ssrRenderClass(ui.value.wrapper({ class: unref(props).ui?.wrapper }))}"${_scopeId}>`);
296
+ if (unref(props).title || !!slots.title) {
297
+ _push(`<div data-slot="title" class="${ssrRenderClass(ui.value.title({ class: unref(props).ui?.title }))}"${_scopeId}>`);
298
+ ssrRenderSlot(_ctx.$slots, "title", {}, () => {
299
+ _push(`${ssrInterpolate(unref(props).title)}`);
300
+ }, _push, _parent, _scopeId);
301
+ _push(`</div>`);
302
+ } else _push(`<!---->`);
303
+ if (unref(props).description || !!slots.description) {
304
+ _push(`<div data-slot="description" class="${ssrRenderClass(ui.value.description({ class: unref(props).ui?.description }))}"${_scopeId}>`);
305
+ ssrRenderSlot(_ctx.$slots, "description", {}, () => {
306
+ _push(`${ssrInterpolate(unref(props).description)}`);
307
+ }, _push, _parent, _scopeId);
308
+ _push(`</div>`);
309
+ } else _push(`<!---->`);
310
+ if (unref(props).orientation === "vertical" && (unref(props).actions?.length || !!slots.actions)) {
311
+ _push(`<div data-slot="actions" class="${ssrRenderClass(ui.value.actions({ class: unref(props).ui?.actions }))}"${_scopeId}>`);
312
+ ssrRenderSlot(_ctx.$slots, "actions", {}, () => {
313
+ _push(`<!--[-->`);
314
+ ssrRenderList(unref(props).actions, (action, index) => {
315
+ _push(ssrRenderComponent(_sfc_main$3, mergeProps({
316
+ key: index,
317
+ size: "xs"
318
+ }, { ref_for: true }, action), null, _parent, _scopeId));
319
+ });
320
+ _push(`<!--]-->`);
321
+ }, _push, _parent, _scopeId);
322
+ _push(`</div>`);
323
+ } else _push(`<!---->`);
324
+ _push(`</div>`);
325
+ if (unref(props).orientation === "horizontal" && (unref(props).actions?.length || !!slots.actions) || unref(props).close) {
326
+ _push(`<div data-slot="actions" class="${ssrRenderClass(ui.value.actions({
327
+ class: unref(props).ui?.actions,
328
+ orientation: "horizontal"
329
+ }))}"${_scopeId}>`);
330
+ if (unref(props).orientation === "horizontal" && (unref(props).actions?.length || !!slots.actions)) ssrRenderSlot(_ctx.$slots, "actions", {}, () => {
331
+ _push(`<!--[-->`);
332
+ ssrRenderList(unref(props).actions, (action, index) => {
333
+ _push(ssrRenderComponent(_sfc_main$3, mergeProps({
334
+ key: index,
335
+ size: "xs"
336
+ }, { ref_for: true }, action), null, _parent, _scopeId));
337
+ });
338
+ _push(`<!--]-->`);
339
+ }, _push, _parent, _scopeId);
340
+ else _push(`<!---->`);
341
+ ssrRenderSlot(_ctx.$slots, "close", { ui: ui.value }, () => {
342
+ if (unref(props).close) _push(ssrRenderComponent(_sfc_main$3, mergeProps({
343
+ icon: unref(props).closeIcon || unref(appConfig).ui.icons.close,
344
+ color: "neutral",
345
+ variant: "link",
346
+ "aria-label": unref(t)("alert.close")
347
+ }, typeof unref(props).close === "object" ? unref(props).close : {}, {
348
+ "data-slot": "close",
349
+ class: ui.value.close({ class: unref(props).ui?.close }),
350
+ onClick: ($event) => emits("update:open", false)
351
+ }), null, _parent, _scopeId));
352
+ else _push(`<!---->`);
353
+ }, _push, _parent, _scopeId);
354
+ _push(`</div>`);
355
+ } else _push(`<!---->`);
356
+ } else return [
357
+ renderSlot(_ctx.$slots, "leading", { ui: ui.value }, () => [unref(props).avatar ? (openBlock(), createBlock(_sfc_main$6, mergeProps({
358
+ key: 0,
359
+ size: unref(props).ui?.avatarSize || ui.value.avatarSize()
360
+ }, unref(props).avatar, {
361
+ "data-slot": "avatar",
362
+ class: ui.value.avatar({ class: unref(props).ui?.avatar })
363
+ }), null, 16, ["size", "class"])) : unref(props).icon ? (openBlock(), createBlock(_sfc_main$8, {
364
+ key: 1,
365
+ name: unref(props).icon,
366
+ "data-slot": "icon",
367
+ class: ui.value.icon({ class: unref(props).ui?.icon })
368
+ }, null, 8, ["name", "class"])) : createCommentVNode("", true)]),
369
+ createVNode("div", {
370
+ "data-slot": "wrapper",
371
+ class: ui.value.wrapper({ class: unref(props).ui?.wrapper })
372
+ }, [
373
+ unref(props).title || !!slots.title ? (openBlock(), createBlock("div", {
374
+ key: 0,
375
+ "data-slot": "title",
376
+ class: ui.value.title({ class: unref(props).ui?.title })
377
+ }, [renderSlot(_ctx.$slots, "title", {}, () => [createTextVNode(toDisplayString(unref(props).title), 1)])], 2)) : createCommentVNode("", true),
378
+ unref(props).description || !!slots.description ? (openBlock(), createBlock("div", {
379
+ key: 1,
380
+ "data-slot": "description",
381
+ class: ui.value.description({ class: unref(props).ui?.description })
382
+ }, [renderSlot(_ctx.$slots, "description", {}, () => [createTextVNode(toDisplayString(unref(props).description), 1)])], 2)) : createCommentVNode("", true),
383
+ unref(props).orientation === "vertical" && (unref(props).actions?.length || !!slots.actions) ? (openBlock(), createBlock("div", {
384
+ key: 2,
385
+ "data-slot": "actions",
386
+ class: ui.value.actions({ class: unref(props).ui?.actions })
387
+ }, [renderSlot(_ctx.$slots, "actions", {}, () => [(openBlock(true), createBlock(Fragment, null, renderList(unref(props).actions, (action, index) => {
388
+ return openBlock(), createBlock(_sfc_main$3, mergeProps({
389
+ key: index,
390
+ size: "xs"
391
+ }, { ref_for: true }, action), null, 16);
392
+ }), 128))])], 2)) : createCommentVNode("", true)
393
+ ], 2),
394
+ unref(props).orientation === "horizontal" && (unref(props).actions?.length || !!slots.actions) || unref(props).close ? (openBlock(), createBlock("div", {
395
+ key: 0,
396
+ "data-slot": "actions",
397
+ class: ui.value.actions({
398
+ class: unref(props).ui?.actions,
399
+ orientation: "horizontal"
400
+ })
401
+ }, [unref(props).orientation === "horizontal" && (unref(props).actions?.length || !!slots.actions) ? renderSlot(_ctx.$slots, "actions", {}, () => [(openBlock(true), createBlock(Fragment, null, renderList(unref(props).actions, (action, index) => {
402
+ return openBlock(), createBlock(_sfc_main$3, mergeProps({
403
+ key: index,
404
+ size: "xs"
405
+ }, { ref_for: true }, action), null, 16);
406
+ }), 128))], void 0, 0) : createCommentVNode("", true), renderSlot(_ctx.$slots, "close", { ui: ui.value }, () => [unref(props).close ? (openBlock(), createBlock(_sfc_main$3, mergeProps({
407
+ key: 0,
408
+ icon: unref(props).closeIcon || unref(appConfig).ui.icons.close,
409
+ color: "neutral",
410
+ variant: "link",
411
+ "aria-label": unref(t)("alert.close")
412
+ }, typeof unref(props).close === "object" ? unref(props).close : {}, {
413
+ "data-slot": "close",
414
+ class: ui.value.close({ class: unref(props).ui?.close }),
415
+ onClick: ($event) => emits("update:open", false)
416
+ }), null, 16, [
417
+ "icon",
418
+ "aria-label",
419
+ "class",
420
+ "onClick"
421
+ ])) : createCommentVNode("", true)])], 2)) : createCommentVNode("", true)
422
+ ];
423
+ }),
424
+ _: 3
425
+ }, _parent));
426
+ };
427
+ }
428
+ };
429
+ var _sfc_setup$12 = _sfc_main.setup;
430
+ _sfc_main.setup = (props, ctx) => {
431
+ const ssrContext = useSSRContext();
432
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("../node_modules/.pnpm/@nuxt+ui@4.10.0_e9e3fcf18fb997bdd8dc5f7c218a2205/node_modules/@nuxt/ui/dist/runtime/components/Alert.vue");
433
+ return _sfc_setup$12 ? _sfc_setup$12(props, ctx) : void 0;
434
+ };
435
+ //#endregion
436
+ //#region app/components/scenario/warnings.vue?vue&type=script&setup=true&lang.ts
437
+ var EMPTY_VAR = "env-sem-valor";
438
+ /** O texto da ressalva, sem o slug da regra que o backend prefixa. */
439
+ var warnings_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
440
+ __name: "warnings",
441
+ __ssrInlineRender: true,
442
+ props: {
443
+ warnings: { default: () => [] },
444
+ slug: {}
445
+ },
446
+ setup(__props) {
447
+ const reasons = computed(() => __props.warnings.map((warning) => warning.replace(/^[a-z-]+: /, "")));
448
+ const fillable = computed(() => __props.warnings.some((warning) => warning.startsWith(EMPTY_VAR)));
449
+ return (_ctx, _push, _parent, _attrs) => {
450
+ const _component_UAlert = _sfc_main;
451
+ const _component_UButton = _sfc_main$3;
452
+ if (__props.warnings.length) _push(ssrRenderComponent(_component_UAlert, mergeProps({
453
+ color: "warning",
454
+ variant: "soft",
455
+ icon: "i-ic-round-warning",
456
+ title: "A geração terminou com ressalvas",
457
+ "data-testid": "geracao-ressalvas"
458
+ }, _attrs), {
459
+ description: withCtx((_, _push, _parent, _scopeId) => {
460
+ if (_push) {
461
+ _push(`<ul class="list-disc pl-4"${_scopeId}><!--[-->`);
462
+ ssrRenderList(unref(reasons), (reason) => {
463
+ _push(`<li${_scopeId}>${ssrInterpolate(reason)}</li>`);
464
+ });
465
+ _push(`<!--]--></ul>`);
466
+ if (unref(fillable)) _push(ssrRenderComponent(_component_UButton, {
467
+ label: "Preencher ambiente",
468
+ "trailing-icon": "i-ic-round-arrow-forward",
469
+ color: "warning",
470
+ variant: "link",
471
+ class: "mt-1 px-0",
472
+ to: `/projects/${__props.slug}?environment`,
473
+ "data-testid": "ressalvas-ambiente"
474
+ }, null, _parent, _scopeId));
475
+ else _push(`<!---->`);
476
+ } else return [createVNode("ul", { class: "list-disc pl-4" }, [(openBlock(true), createBlock(Fragment, null, renderList(unref(reasons), (reason) => {
477
+ return openBlock(), createBlock("li", { key: reason }, toDisplayString(reason), 1);
478
+ }), 128))]), unref(fillable) ? (openBlock(), createBlock(_component_UButton, {
479
+ key: 0,
480
+ label: "Preencher ambiente",
481
+ "trailing-icon": "i-ic-round-arrow-forward",
482
+ color: "warning",
483
+ variant: "link",
484
+ class: "mt-1 px-0",
485
+ to: `/projects/${__props.slug}?environment`,
486
+ "data-testid": "ressalvas-ambiente"
487
+ }, null, 8, ["to"])) : createCommentVNode("", true)];
488
+ }),
489
+ _: 1
490
+ }, _parent));
491
+ else _push(`<!---->`);
492
+ };
493
+ }
494
+ });
495
+ //#endregion
496
+ //#region app/components/scenario/warnings.vue
497
+ var _sfc_setup$11 = warnings_vue_vue_type_script_setup_true_lang_default.setup;
498
+ warnings_vue_vue_type_script_setup_true_lang_default.setup = (props, ctx) => {
499
+ const ssrContext = useSSRContext();
500
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/scenario/warnings.vue");
501
+ return _sfc_setup$11 ? _sfc_setup$11(props, ctx) : void 0;
502
+ };
503
+ var warnings_default = Object.assign(warnings_vue_vue_type_script_setup_true_lang_default, { __name: "ScenarioWarnings" });
504
+ //#endregion
505
+ //#region node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_45e57be3aa7485e3075b5014322cbc65/node_modules/nuxt/dist/app/composables/url.js
506
+ /** @since 3.5.0 */
507
+ function useRequestURL(opts) {
508
+ return getRequestURL(useRequestEvent(), opts);
509
+ }
510
+ //#endregion
511
+ //#region app/components/webdriver/setup.vue?vue&type=script&setup=true&lang.ts
512
+ var setup_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
513
+ __name: "setup",
514
+ __ssrInlineRender: true,
515
+ setup(__props) {
516
+ const os = ref("macos");
517
+ const tabs = [
518
+ {
519
+ label: "macOS",
520
+ value: "macos"
521
+ },
522
+ {
523
+ label: "Linux",
524
+ value: "linux"
525
+ },
526
+ {
527
+ label: "Windows",
528
+ value: "windows"
529
+ }
530
+ ];
531
+ const route = useRoute();
532
+ const origin = useRequestURL().origin;
533
+ const currentUrl = computed(() => `${origin}${route.fullPath}`);
534
+ const commands = computed(() => ({
535
+ macos: `open -na "Google Chrome" --args --remote-debugging-port=9222 --user-data-dir="$HOME/.acutis/chrome" "${currentUrl.value}"`,
536
+ linux: `google-chrome --remote-debugging-port=9222 --user-data-dir="$HOME/.acutis/chrome" "${currentUrl.value}" &`,
537
+ windows: `Start-Process "chrome" -ArgumentList "--remote-debugging-port=9222","--user-data-dir=$env:USERPROFILE\\.acutis\\chrome","${currentUrl.value}"`
538
+ }));
539
+ const copied = ref(false);
540
+ let copiedTimer;
541
+ async function copy() {
542
+ await (void 0).clipboard.writeText(commands.value[os.value]);
543
+ copied.value = true;
544
+ clearTimeout(copiedTimer);
545
+ copiedTimer = setTimeout(() => {
546
+ copied.value = false;
547
+ }, 2e3);
548
+ }
549
+ return (_ctx, _push, _parent, _attrs) => {
550
+ const _component_UTabs = _sfc_main$1;
551
+ const _component_BaseButtonIcon = icon_default;
552
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "flex flex-col gap-3 rounded-lg bg-elevated p-4" }, _attrs))}><p class="text-sm text-muted"> Abra o Chrome com a porta de depuração. Ele já abre nesta página, é só clicar em <span class="font-medium text-default">Novo cenário</span> de novo: </p>`);
553
+ _push(ssrRenderComponent(_component_UTabs, {
554
+ modelValue: unref(os),
555
+ "onUpdate:modelValue": ($event) => isRef(os) ? os.value = $event : null,
556
+ items: tabs,
557
+ content: false,
558
+ class: "w-full"
559
+ }, null, _parent));
560
+ _push(`<div class="flex items-center gap-2"><code data-testid="webdriver-comando" class="grow overflow-x-auto whitespace-nowrap rounded-md bg-default p-3 text-xs">${ssrInterpolate(unref(commands)[unref(os)])}</code>`);
561
+ _push(ssrRenderComponent(_component_BaseButtonIcon, {
562
+ icon: unref(copied) ? "i-ic-round-check" : "i-ic-round-content-copy",
563
+ label: unref(copied) ? "Copiado!" : "Copiar comando",
564
+ color: "neutral",
565
+ variant: "soft",
566
+ "data-testid": "webdriver-copiar",
567
+ onClick: copy
568
+ }, null, _parent));
569
+ _push(`</div></div>`);
570
+ };
571
+ }
572
+ });
573
+ //#endregion
574
+ //#region app/components/webdriver/setup.vue
575
+ var _sfc_setup$10 = setup_vue_vue_type_script_setup_true_lang_default.setup;
576
+ setup_vue_vue_type_script_setup_true_lang_default.setup = (props, ctx) => {
577
+ const ssrContext = useSSRContext();
578
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/webdriver/setup.vue");
579
+ return _sfc_setup$10 ? _sfc_setup$10(props, ctx) : void 0;
580
+ };
581
+ var setup_default = Object.assign(setup_vue_vue_type_script_setup_true_lang_default, { __name: "WebdriverSetup" });
582
+ //#endregion
583
+ //#region app/components/base/empty.vue?vue&type=script&setup=true&lang.ts
584
+ var empty_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
585
+ __name: "empty",
586
+ __ssrInlineRender: true,
587
+ props: {
588
+ icon: {},
589
+ title: {},
590
+ description: { default: "" },
591
+ testid: { default: "" }
592
+ },
593
+ setup(__props) {
594
+ return (_ctx, _push, _parent, _attrs) => {
595
+ const _component_UIcon = _sfc_main$8;
596
+ _push(`<div${ssrRenderAttrs(mergeProps({
597
+ class: "flex flex-col items-center gap-3 py-10 text-center",
598
+ "data-testid": __props.testid
599
+ }, _attrs))}><div class="flex size-12 items-center justify-center rounded-lg bg-elevated">`);
600
+ _push(ssrRenderComponent(_component_UIcon, {
601
+ name: __props.icon,
602
+ class: "size-7 text-dimmed"
603
+ }, null, _parent));
604
+ _push(`</div><p class="font-semibold">${ssrInterpolate(__props.title)}</p>`);
605
+ if (__props.description) _push(`<p class="max-w-sm text-sm text-muted">${ssrInterpolate(__props.description)}</p>`);
606
+ else _push(`<!---->`);
607
+ _push(`</div>`);
608
+ };
609
+ }
610
+ });
611
+ //#endregion
612
+ //#region app/components/base/empty.vue
613
+ var _sfc_setup$9 = empty_vue_vue_type_script_setup_true_lang_default.setup;
614
+ empty_vue_vue_type_script_setup_true_lang_default.setup = (props, ctx) => {
615
+ const ssrContext = useSSRContext();
616
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/base/empty.vue");
617
+ return _sfc_setup$9 ? _sfc_setup$9(props, ctx) : void 0;
618
+ };
619
+ var empty_default = Object.assign(empty_vue_vue_type_script_setup_true_lang_default, { __name: "BaseEmpty" });
620
+ //#endregion
621
+ //#region app/utils/recorder-event.ts
622
+ /** A gravação como o backend a guarda: os campos do evento, sem o que é do transporte. */
623
+ function toRecordedEvents(events) {
624
+ return events.map((event) => ({
625
+ type: event.type,
626
+ timestamp: event.timestamp,
627
+ url: event.url ?? null,
628
+ selectors: event.selectors ?? null,
629
+ label: event.label ?? null,
630
+ innerText: event.innerText ?? null,
631
+ tagName: event.tagName ?? null,
632
+ inputType: event.inputType ?? null,
633
+ value: event.value ?? null,
634
+ sensitive: event.sensitive ?? false,
635
+ checked: event.checked ?? null,
636
+ html: event.html ?? null,
637
+ assert: event.assert
638
+ }));
639
+ }
640
+ /** Como o evento chama o elemento, na mesma ordem de fontes do `SpecEmitter` do backend. */
641
+ function target(event) {
642
+ const selectors = event.selectors;
643
+ const clean = (event.label || event.innerText || selectors?.placeholder || selectors?.text || "").replace(/\s+/g, " ").trim();
644
+ return clean === "" ? null : clean;
645
+ }
646
+ /** O alvo entre aspas, separando o que veio da tela do verbo que o descreve. */
647
+ function quoted(what) {
648
+ return `"${what}"`;
649
+ }
650
+ /** O caminho da URL, que é como a execução chama a tela: "/login", ou a página inicial na raiz. */
651
+ function page(event) {
652
+ const url = event.url ?? "";
653
+ try {
654
+ const path = new URL(url, "http://base.test").pathname;
655
+ return path === "/" ? "a página inicial" : quoted(path);
656
+ } catch {
657
+ return url ? quoted(url) : "a página inicial";
658
+ }
659
+ }
660
+ /**
661
+ * A frase que descreve o evento gravado, no mesmo vocabulário dos passos da execução
662
+ * ("Clica em Entrar", "Preenche Senha"). A navegação é dita pelo caminho da URL.
663
+ */
664
+ function describeRecorderEvent(event) {
665
+ const what = target(event);
666
+ switch (event.type) {
667
+ case "navigate": return `Navega para ${page(event)}`;
668
+ case "click": return what ? `Clica em ${quoted(what)}` : "Clica no elemento";
669
+ case "hover": return what ? `Passa o mouse em ${quoted(what)}` : "Passa o mouse no elemento";
670
+ case "fill": {
671
+ const field = what ? quoted(what) : "o campo";
672
+ if (!event.value) return `Preenche ${field}`;
673
+ return `Preenche ${field} com ${event.sensitive ? "••••" : quoted(event.value)}`;
674
+ }
675
+ case "submit": return "Envia o formulário";
676
+ case "assert":
677
+ if (event.assert?.assertType === "url") return `Confere que a tela é ${page(event)}`;
678
+ return `Confere ${what ? quoted(what) : "o elemento"}`;
679
+ default: return what ?? event.url ?? event.type ?? "";
680
+ }
681
+ }
682
+ //#endregion
683
+ //#region app/components/scenario/review/timeline.vue?vue&type=script&setup=true&lang.ts
684
+ var timeline_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
685
+ __name: "timeline",
686
+ __ssrInlineRender: true,
687
+ props: {
688
+ events: {},
689
+ videoSrc: { default: null },
690
+ recordingStartedAt: { default: null },
691
+ resumable: {
692
+ type: Boolean,
693
+ default: false
694
+ }
695
+ },
696
+ emits: ["resume"],
697
+ setup(__props, { emit: __emit }) {
698
+ ref(null);
699
+ const currentTime = ref(0);
700
+ const armed = ref(null);
701
+ const ready = ref(false);
702
+ const eventIcons = {
703
+ navigate: "i-ic-round-public",
704
+ click: "i-ic-round-ads-click",
705
+ fill: "i-ic-round-edit",
706
+ submit: "i-ic-round-send",
707
+ hover: "i-ic-round-mouse",
708
+ assert: "i-ic-round-check-circle"
709
+ };
710
+ function offsetSeconds(event) {
711
+ if (!__props.recordingStartedAt || !event.timestamp) return 0;
712
+ return Math.max(0, (event.timestamp - __props.recordingStartedAt) / 1e3);
713
+ }
714
+ const currentIndex = computed(() => {
715
+ let index = -1;
716
+ __props.events.forEach((event, i) => {
717
+ if (offsetSeconds(event) <= currentTime.value) index = i;
718
+ });
719
+ return index;
720
+ });
721
+ /** Quantos passos saem da gravação quando o corte armado for confirmado. */
722
+ const dropped = computed(() => armed.value === null ? 0 : __props.events.length - armed.value);
723
+ return (_ctx, _push, _parent, _attrs) => {
724
+ const _component_UIcon = _sfc_main$8;
725
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "grid grid-cols-1 gap-6 lg:grid-cols-5" }, _attrs))} data-v-46efcf33>`);
726
+ if (__props.videoSrc) _push(`<video data-testid="revisao-video"${ssrRenderAttr("src", __props.videoSrc)} controls class="w-full self-start rounded-lg lg:sticky lg:top-0 lg:col-span-3" data-v-46efcf33></video>`);
727
+ else _push(`<!---->`);
728
+ _push(`<div class="${ssrRenderClass(__props.videoSrc ? "lg:col-span-2" : "lg:col-span-5")}" data-v-46efcf33><p class="mb-3 font-semibold" data-v-46efcf33> Timeline dos eventos </p><ol class="flex w-max max-w-full flex-col" data-v-46efcf33><!--[-->`);
729
+ ssrRenderList(__props.events, (event, i) => {
730
+ _push(`<li data-testid="revisao-evento"${ssrRenderAttr("data-current", i === unref(currentIndex) ? "true" : "false")}${ssrRenderAttr("data-dropped", unref(armed) !== null && i >= unref(armed) ? "true" : "false")} class="${ssrRenderClass([unref(armed) !== null && i >= unref(armed) ? "opacity-50" : "", "group relative flex cursor-pointer items-stretch gap-3 transition-opacity"])}" data-v-46efcf33>`);
731
+ if (__props.resumable && i > 0) {
732
+ _push(`<button type="button" data-testid="revisao-retomar"${ssrRenderAttr("data-armed", unref(armed) === i ? "true" : "false")} class="${ssrRenderClass([unref(armed) === i ? "opacity-100!" : "", "absolute -top-5 -right-1.5 -left-1.5 z-10 flex h-4 items-center gap-2 opacity-0 transition-opacity focus-visible:opacity-100 group-hover:opacity-100"])}"${ssrRenderAttr("aria-label", unref(armed) === i ? `Confirmar a retomada deste passo, descartando ${unref(dropped)}` : "Retomar a gravação deste passo")} data-v-46efcf33><span class="${ssrRenderClass([unref(armed) === i ? "bg-error" : "bg-primary", "h-px flex-1 rounded-full"])}" data-v-46efcf33></span><span class="${ssrRenderClass([unref(armed) === i ? "bg-error text-inverted" : "bg-default text-primary", "rounded-full px-2 py-0.5 text-[10px] leading-none font-medium tracking-wide uppercase"])}" data-v-46efcf33>`);
733
+ if (unref(armed) !== i) _push(`<!--[-->retomar daqui<!--]-->`);
734
+ else if (unref(ready)) _push(`<!--[-->clique de novo · descarta ${ssrInterpolate(unref(dropped))}<!--]-->`);
735
+ else _push(`<!--[-->aguarde…<!--]-->`);
736
+ _push(`</span><span class="relative h-px flex-1 overflow-visible rounded-full bg-accented" data-v-46efcf33>`);
737
+ if (unref(armed) === i) _push(`<span class="arming absolute inset-y-0 left-0 rounded-full bg-error" data-v-46efcf33></span>`);
738
+ else _push(`<!---->`);
739
+ _push(`</span></button>`);
740
+ } else _push(`<!---->`);
741
+ _push(`<div class="flex flex-col items-center" data-v-46efcf33>`);
742
+ _push(ssrRenderComponent(_component_UIcon, {
743
+ name: eventIcons[event.type] ?? "i-ic-round-help-outline",
744
+ class: ["size-5 shrink-0 transition-colors", i <= unref(currentIndex) ? "text-primary" : "text-muted"]
745
+ }, null, _parent));
746
+ if (i < __props.events.length - 1) _push(`<span class="${ssrRenderClass([i < unref(currentIndex) ? "bg-primary" : "bg-accented", "w-px grow transition-colors"])}" data-v-46efcf33></span>`);
747
+ else _push(`<!---->`);
748
+ _push(`</div><div class="pb-6 min-w-0 flex-1" data-v-46efcf33><p class="${ssrRenderClass([[i === unref(currentIndex) ? "font-semibold text-primary" : "text-default", unref(armed) !== null && i >= unref(armed) ? "line-through decoration-dimmed" : ""], "truncate text-sm transition-colors group-hover:text-highlighted"])}" data-v-46efcf33>${ssrInterpolate(unref(describeRecorderEvent)(event))}</p>`);
749
+ if (__props.recordingStartedAt) _push(`<p class="text-xs text-dimmed" data-v-46efcf33>${ssrInterpolate(offsetSeconds(event).toFixed(1))}s </p>`);
750
+ else _push(`<!---->`);
751
+ _push(`</div></li>`);
752
+ });
753
+ _push(`<!--]--></ol></div></div>`);
754
+ };
755
+ }
756
+ });
757
+ //#endregion
758
+ //#region app/components/scenario/review/timeline.vue
759
+ var _sfc_setup$8 = timeline_vue_vue_type_script_setup_true_lang_default.setup;
760
+ timeline_vue_vue_type_script_setup_true_lang_default.setup = (props, ctx) => {
761
+ const ssrContext = useSSRContext();
762
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/scenario/review/timeline.vue");
763
+ return _sfc_setup$8 ? _sfc_setup$8(props, ctx) : void 0;
764
+ };
765
+ var timeline_default = /*#__PURE__*/ Object.assign(_plugin_vue_export_helper_default(timeline_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-46efcf33"]]), { __name: "ScenarioReviewTimeline" });
766
+ //#endregion
767
+ //#region app/components/base/codefield.vue?vue&type=script&setup=true&lang.ts
768
+ var codefield_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
769
+ __name: "codefield",
770
+ __ssrInlineRender: true,
771
+ props: /*@__PURE__*/ mergeModels({
772
+ language: {},
773
+ testid: {},
774
+ readonly: {
775
+ type: Boolean,
776
+ default: false
777
+ }
778
+ }, {
779
+ "modelValue": { default: "" },
780
+ "modelModifiers": {}
781
+ }),
782
+ emits: ["update:modelValue"],
783
+ setup(__props) {
784
+ const model = useModel(__props, "modelValue");
785
+ const textarea = ref(null);
786
+ function renderTokens(stream) {
787
+ if (typeof stream === "string") return [stream];
788
+ if (Array.isArray(stream)) return stream.flatMap(renderTokens);
789
+ const aliases = Array.isArray(stream.alias) ? stream.alias : [stream.alias].filter(Boolean);
790
+ return [h("span", { class: [
791
+ "token",
792
+ stream.type,
793
+ ...aliases
794
+ ] }, renderTokens(stream.content))];
795
+ }
796
+ const highlighted = computed(() => [...Prism.tokenize(model.value, Prism.languages[__props.language]), "\n"]);
797
+ const HighlightedCode = defineComponent(() => () => h("code", null, renderTokens(highlighted.value)));
798
+ function resize() {
799
+ const el = textarea.value;
800
+ if (!el) return;
801
+ el.style.height = "auto";
802
+ el.style.height = `${el.scrollHeight}px`;
803
+ }
804
+ watch(model, () => nextTick(resize));
805
+ return (_ctx, _push, _parent, _attrs) => {
806
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "codefield relative overflow-hidden rounded-md bg-elevated font-mono text-sm/6" }, _attrs))} data-v-3e187072><pre aria-hidden="true" class="codefield-box pointer-events-none absolute inset-0 m-0 overflow-hidden" data-v-3e187072>`);
807
+ _push(ssrRenderComponent(unref(HighlightedCode), null, null, _parent));
808
+ _push(`</pre><textarea${ssrRenderAttr("data-testid", __props.testid)}${ssrIncludeBooleanAttr(__props.readonly) ? " readonly" : ""} spellcheck="false" class="codefield-box relative block w-full resize-none bg-transparent text-transparent caret-[var(--ui-text-highlighted)] outline-none" data-v-3e187072>${ssrInterpolate(model.value)}</textarea></div>`);
809
+ };
810
+ }
811
+ });
812
+ //#endregion
813
+ //#region app/components/base/codefield.vue
814
+ var _sfc_setup$7 = codefield_vue_vue_type_script_setup_true_lang_default.setup;
815
+ codefield_vue_vue_type_script_setup_true_lang_default.setup = (props, ctx) => {
816
+ const ssrContext = useSSRContext();
817
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/base/codefield.vue");
818
+ return _sfc_setup$7 ? _sfc_setup$7(props, ctx) : void 0;
819
+ };
820
+ var codefield_default = /*#__PURE__*/ Object.assign(_plugin_vue_export_helper_default(codefield_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-3e187072"]]), { __name: "BaseCodefield" });
821
+ //#endregion
822
+ //#region app/components/base/confirm.vue?vue&type=script&setup=true&lang.ts
823
+ var confirm_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
824
+ __name: "confirm",
825
+ __ssrInlineRender: true,
826
+ props: /*@__PURE__*/ mergeModels({
827
+ title: {},
828
+ description: { default: "" },
829
+ confirmLabel: { default: "Confirmar" },
830
+ confirmColor: { default: "primary" },
831
+ confirmTestid: { default: "confirmar" },
832
+ loading: {
833
+ type: Boolean,
834
+ default: false
835
+ }
836
+ }, {
837
+ "open": {
838
+ type: Boolean,
839
+ default: false
840
+ },
841
+ "openModifiers": {}
842
+ }),
843
+ emits: /*@__PURE__*/ mergeModels(["confirm"], ["update:open"]),
844
+ setup(__props, { emit: __emit }) {
845
+ const open = useModel(__props, "open");
846
+ const emit = __emit;
847
+ return (_ctx, _push, _parent, _attrs) => {
848
+ const _component_BaseModal = modal_default$2;
849
+ const _component_UButton = _sfc_main$3;
850
+ _push(ssrRenderComponent(_component_BaseModal, mergeProps({
851
+ open: open.value,
852
+ "onUpdate:open": ($event) => open.value = $event,
853
+ title: __props.title
854
+ }, _attrs), {
855
+ body: withCtx((_, _push, _parent, _scopeId) => {
856
+ if (_push) {
857
+ _push(`<div class="flex min-h-24 items-center justify-center text-center"${_scopeId}><p class="w-full text-lg text-muted break-words"${_scopeId}>`);
858
+ ssrRenderSlot(_ctx.$slots, "description", {}, () => {
859
+ _push(`${ssrInterpolate(__props.description)}`);
860
+ }, _push, _parent, _scopeId);
861
+ _push(`</p></div>`);
862
+ } else return [createVNode("div", { class: "flex min-h-24 items-center justify-center text-center" }, [createVNode("p", { class: "w-full text-lg text-muted break-words" }, [renderSlot(_ctx.$slots, "description", {}, () => [createTextVNode(toDisplayString(__props.description), 1)])])])];
863
+ }),
864
+ footer: withCtx((_, _push, _parent, _scopeId) => {
865
+ if (_push) {
866
+ _push(ssrRenderComponent(_component_UButton, {
867
+ label: "Cancelar",
868
+ color: "neutral",
869
+ variant: "ghost",
870
+ "data-testid": "confirmar-cancelar",
871
+ onClick: ($event) => open.value = false
872
+ }, null, _parent, _scopeId));
873
+ _push(ssrRenderComponent(_component_UButton, {
874
+ label: __props.confirmLabel,
875
+ color: __props.confirmColor,
876
+ loading: __props.loading,
877
+ "data-testid": __props.confirmTestid,
878
+ onClick: ($event) => emit("confirm")
879
+ }, null, _parent, _scopeId));
880
+ } else return [createVNode(_component_UButton, {
881
+ label: "Cancelar",
882
+ color: "neutral",
883
+ variant: "ghost",
884
+ "data-testid": "confirmar-cancelar",
885
+ onClick: ($event) => open.value = false
886
+ }, null, 8, ["onClick"]), createVNode(_component_UButton, {
887
+ label: __props.confirmLabel,
888
+ color: __props.confirmColor,
889
+ loading: __props.loading,
890
+ "data-testid": __props.confirmTestid,
891
+ onClick: ($event) => emit("confirm")
892
+ }, null, 8, [
893
+ "label",
894
+ "color",
895
+ "loading",
896
+ "data-testid",
897
+ "onClick"
898
+ ])];
899
+ }),
900
+ _: 3
901
+ }, _parent));
902
+ };
903
+ }
904
+ });
905
+ //#endregion
906
+ //#region app/components/base/confirm.vue
907
+ var _sfc_setup$6 = confirm_vue_vue_type_script_setup_true_lang_default.setup;
908
+ confirm_vue_vue_type_script_setup_true_lang_default.setup = (props, ctx) => {
909
+ const ssrContext = useSSRContext();
910
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/base/confirm.vue");
911
+ return _sfc_setup$6 ? _sfc_setup$6(props, ctx) : void 0;
912
+ };
913
+ var confirm_default = Object.assign(confirm_vue_vue_type_script_setup_true_lang_default, { __name: "BaseConfirm" });
914
+ /** O nome de arquivo que um título vira. Acompanha o `Str::slug` que o backend aplica ao gravar. */
915
+ function slugify(value) {
916
+ return value.normalize("NFD").replace(/\p{Diacritic}/gu, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 80).replace(/^-+|-+$/g, "");
917
+ }
918
+ function draftFromScenario(scenario) {
919
+ const parts = scenario.spec.replace(/^tests\//, "").replace(/\.spec\.ts$/, "").split("/");
920
+ return {
921
+ title: scenario.title,
922
+ path: parts.at(-1),
923
+ domain: parts.length > 1 ? parts.slice(0, -1).join("/") : "",
924
+ tags: scenario.tags,
925
+ gherkin: scenario.gherkin ?? "",
926
+ playwright: scenario.playwright
927
+ };
928
+ }
929
+ //#endregion
930
+ //#region app/components/scenario/review/contexts.vue?vue&type=script&setup=true&lang.ts
931
+ var contexts_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
932
+ __name: "contexts",
933
+ __ssrInlineRender: true,
934
+ props: /*@__PURE__*/ mergeModels({
935
+ isAuth: {
936
+ type: Boolean,
937
+ default: false
938
+ },
939
+ novo: {
940
+ type: Boolean,
941
+ default: false
942
+ }
943
+ }, {
944
+ "draft": { required: true },
945
+ "draftModifiers": {}
946
+ }),
947
+ emits: ["update:draft"],
948
+ setup(__props) {
949
+ const draft = useModel(__props, "draft");
950
+ function tagsFromLine(line) {
951
+ return line.match(/@[\w-]+/g) ?? [];
952
+ }
953
+ function tagsFromGherkin(gherkin) {
954
+ const firstLine = gherkin.split("\n")[0] ?? "";
955
+ return firstLine.trim().startsWith("@") ? tagsFromLine(firstLine) : [];
956
+ }
957
+ function tagsFromPlaywright(playwright) {
958
+ const match = playwright.match(/tag:\s*\[([^\]]*)\]/);
959
+ return match ? tagsFromLine(match[1]) : [];
960
+ }
961
+ function stampGherkinTags(gherkin, tags) {
962
+ if (!gherkin.trim()) return gherkin;
963
+ const lines = gherkin.split("\n");
964
+ if (lines[0]?.trim().startsWith("@")) lines.shift();
965
+ const body = lines.join("\n");
966
+ return tags.length ? `${tags.join(" ")}\n${body}` : body;
967
+ }
968
+ function stampPlaywrightTags(playwright, tags) {
969
+ if (!tags.length) return playwright;
970
+ const list = `tag: [${tags.map((t) => `'${t}'`).join(", ")}]`;
971
+ if (/tag:\s*\[[^\]]*\]/.test(playwright)) return playwright.replace(/tag:\s*\[[^\]]*\]/, list);
972
+ return playwright.replace(/test\.describe\(\s*((["']).+?\2)\s*,\s*(?=\(|async)/, `test.describe($1, { ${list} }, `);
973
+ }
974
+ let syncing = false;
975
+ function applyTags(tags) {
976
+ syncing = true;
977
+ draft.value = {
978
+ ...draft.value,
979
+ tags,
980
+ gherkin: stampGherkinTags(draft.value.gherkin, tags),
981
+ playwright: stampPlaywrightTags(draft.value.playwright, tags)
982
+ };
983
+ nextTick(() => {
984
+ syncing = false;
985
+ });
986
+ }
987
+ const tagsText = computed({
988
+ get: () => draft.value.tags.join(" "),
989
+ set: (value) => applyTags(tagsFromLine(value))
990
+ });
991
+ watch(() => draft.value.gherkin, (gherkin) => {
992
+ if (syncing) return;
993
+ const tags = tagsFromGherkin(gherkin);
994
+ if (tags.length && tags.join(" ") !== draft.value.tags.join(" ")) applyTags(tags);
995
+ });
996
+ watch(() => draft.value.playwright, (playwright) => {
997
+ if (syncing) return;
998
+ const tags = tagsFromPlaywright(playwright);
999
+ if (tags.length && tags.join(" ") !== draft.value.tags.join(" ")) applyTags(tags);
1000
+ });
1001
+ /** No cenário novo o arquivo espelha o título, enquanto ninguém o tiver editado à mão. */
1002
+ watch(() => draft.value.title, (title, previous) => {
1003
+ if (!__props.novo || draft.value.path !== slugify(previous)) return;
1004
+ draft.value = {
1005
+ ...draft.value,
1006
+ path: slugify(title)
1007
+ };
1008
+ });
1009
+ return (_ctx, _push, _parent, _attrs) => {
1010
+ const _component_UFormField = _sfc_main$1$1;
1011
+ const _component_UInput = _sfc_main$4;
1012
+ const _component_BaseCodefield = codefield_default;
1013
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "flex flex-col gap-5" }, _attrs))}><div class="grid grid-cols-1 gap-4 sm:grid-cols-2">`);
1014
+ _push(ssrRenderComponent(_component_UFormField, { label: "Título do cenário" }, {
1015
+ default: withCtx((_, _push, _parent, _scopeId) => {
1016
+ if (_push) _push(ssrRenderComponent(_component_UInput, {
1017
+ modelValue: draft.value.title,
1018
+ "onUpdate:modelValue": ($event) => draft.value.title = $event,
1019
+ maxlength: unref(120),
1020
+ "data-testid": "contexto-titulo",
1021
+ class: "w-full"
1022
+ }, null, _parent, _scopeId));
1023
+ else return [createVNode(_component_UInput, {
1024
+ modelValue: draft.value.title,
1025
+ "onUpdate:modelValue": ($event) => draft.value.title = $event,
1026
+ maxlength: unref(120),
1027
+ "data-testid": "contexto-titulo",
1028
+ class: "w-full"
1029
+ }, null, 8, [
1030
+ "modelValue",
1031
+ "onUpdate:modelValue",
1032
+ "maxlength"
1033
+ ])];
1034
+ }),
1035
+ _: 1
1036
+ }, _parent));
1037
+ if (!__props.isAuth) _push(ssrRenderComponent(_component_UFormField, {
1038
+ label: "Arquivo",
1039
+ help: "Nome do .spec.ts / .feature"
1040
+ }, {
1041
+ default: withCtx((_, _push, _parent, _scopeId) => {
1042
+ if (_push) _push(ssrRenderComponent(_component_UInput, {
1043
+ modelValue: draft.value.path,
1044
+ "onUpdate:modelValue": ($event) => draft.value.path = $event,
1045
+ maxlength: unref(80),
1046
+ "data-testid": "contexto-path",
1047
+ class: "w-full"
1048
+ }, null, _parent, _scopeId));
1049
+ else return [createVNode(_component_UInput, {
1050
+ modelValue: draft.value.path,
1051
+ "onUpdate:modelValue": ($event) => draft.value.path = $event,
1052
+ maxlength: unref(80),
1053
+ "data-testid": "contexto-path",
1054
+ class: "w-full"
1055
+ }, null, 8, [
1056
+ "modelValue",
1057
+ "onUpdate:modelValue",
1058
+ "maxlength"
1059
+ ])];
1060
+ }),
1061
+ _: 1
1062
+ }, _parent));
1063
+ else _push(`<!---->`);
1064
+ _push(`</div>`);
1065
+ if (!__props.isAuth) _push(ssrRenderComponent(_component_UFormField, {
1066
+ label: "Domínio",
1067
+ help: "Pasta onde o cenário será salvo (ex.: login, checkout)"
1068
+ }, {
1069
+ default: withCtx((_, _push, _parent, _scopeId) => {
1070
+ if (_push) _push(ssrRenderComponent(_component_UInput, {
1071
+ modelValue: draft.value.domain,
1072
+ "onUpdate:modelValue": ($event) => draft.value.domain = $event,
1073
+ maxlength: unref(80),
1074
+ "data-testid": "contexto-dominio",
1075
+ class: "w-full"
1076
+ }, null, _parent, _scopeId));
1077
+ else return [createVNode(_component_UInput, {
1078
+ modelValue: draft.value.domain,
1079
+ "onUpdate:modelValue": ($event) => draft.value.domain = $event,
1080
+ maxlength: unref(80),
1081
+ "data-testid": "contexto-dominio",
1082
+ class: "w-full"
1083
+ }, null, 8, [
1084
+ "modelValue",
1085
+ "onUpdate:modelValue",
1086
+ "maxlength"
1087
+ ])];
1088
+ }),
1089
+ _: 1
1090
+ }, _parent));
1091
+ else _push(`<!---->`);
1092
+ if (!__props.isAuth) _push(ssrRenderComponent(_component_UFormField, {
1093
+ label: "Tags",
1094
+ help: "Separadas por espaço (ex.: @read @criando)"
1095
+ }, {
1096
+ default: withCtx((_, _push, _parent, _scopeId) => {
1097
+ if (_push) _push(ssrRenderComponent(_component_UInput, {
1098
+ modelValue: unref(tagsText),
1099
+ "onUpdate:modelValue": ($event) => isRef(tagsText) ? tagsText.value = $event : null,
1100
+ "data-testid": "contexto-tags",
1101
+ class: "w-full"
1102
+ }, null, _parent, _scopeId));
1103
+ else return [createVNode(_component_UInput, {
1104
+ modelValue: unref(tagsText),
1105
+ "onUpdate:modelValue": ($event) => isRef(tagsText) ? tagsText.value = $event : null,
1106
+ "data-testid": "contexto-tags",
1107
+ class: "w-full"
1108
+ }, null, 8, ["modelValue", "onUpdate:modelValue"])];
1109
+ }),
1110
+ _: 1
1111
+ }, _parent));
1112
+ else _push(`<!---->`);
1113
+ _push(ssrRenderComponent(_component_UFormField, { label: "Cenário (Gherkin)" }, {
1114
+ default: withCtx((_, _push, _parent, _scopeId) => {
1115
+ if (_push) _push(ssrRenderComponent(_component_BaseCodefield, {
1116
+ modelValue: draft.value.gherkin,
1117
+ "onUpdate:modelValue": ($event) => draft.value.gherkin = $event,
1118
+ language: "gherkin",
1119
+ testid: "contexto-cenario"
1120
+ }, null, _parent, _scopeId));
1121
+ else return [createVNode(_component_BaseCodefield, {
1122
+ modelValue: draft.value.gherkin,
1123
+ "onUpdate:modelValue": ($event) => draft.value.gherkin = $event,
1124
+ language: "gherkin",
1125
+ testid: "contexto-cenario"
1126
+ }, null, 8, ["modelValue", "onUpdate:modelValue"])];
1127
+ }),
1128
+ _: 1
1129
+ }, _parent));
1130
+ _push(ssrRenderComponent(_component_UFormField, { label: "Teste (Playwright)" }, {
1131
+ default: withCtx((_, _push, _parent, _scopeId) => {
1132
+ if (_push) _push(ssrRenderComponent(_component_BaseCodefield, {
1133
+ modelValue: draft.value.playwright,
1134
+ "onUpdate:modelValue": ($event) => draft.value.playwright = $event,
1135
+ language: "typescript",
1136
+ testid: "contexto-teste"
1137
+ }, null, _parent, _scopeId));
1138
+ else return [createVNode(_component_BaseCodefield, {
1139
+ modelValue: draft.value.playwright,
1140
+ "onUpdate:modelValue": ($event) => draft.value.playwright = $event,
1141
+ language: "typescript",
1142
+ testid: "contexto-teste"
1143
+ }, null, 8, ["modelValue", "onUpdate:modelValue"])];
1144
+ }),
1145
+ _: 1
1146
+ }, _parent));
1147
+ _push(`</div>`);
1148
+ };
1149
+ }
1150
+ });
1151
+ //#endregion
1152
+ //#region app/components/scenario/review/contexts.vue
1153
+ var _sfc_setup$5 = contexts_vue_vue_type_script_setup_true_lang_default.setup;
1154
+ contexts_vue_vue_type_script_setup_true_lang_default.setup = (props, ctx) => {
1155
+ const ssrContext = useSSRContext();
1156
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/scenario/review/contexts.vue");
1157
+ return _sfc_setup$5 ? _sfc_setup$5(props, ctx) : void 0;
1158
+ };
1159
+ var contexts_default = Object.assign(contexts_vue_vue_type_script_setup_true_lang_default, { __name: "ScenarioReviewContexts" });
1160
+ //#endregion
1161
+ //#region app/components/base/loading/phrases.vue?vue&type=script&setup=true&lang.ts
1162
+ var phrases_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
1163
+ __name: "phrases",
1164
+ __ssrInlineRender: true,
1165
+ props: {
1166
+ phrases: {},
1167
+ icon: { default: "i-line-md-coffee-half-empty-twotone-loop" },
1168
+ hint: { default: "Isso pode levar alguns segundos." }
1169
+ },
1170
+ setup(__props) {
1171
+ const display = ref(__props.phrases[0]);
1172
+ return (_ctx, _push, _parent, _attrs) => {
1173
+ const _component_UIcon = _sfc_main$8;
1174
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "flex flex-col items-center gap-6 py-10 text-center" }, _attrs))}>`);
1175
+ _push(ssrRenderComponent(_component_UIcon, {
1176
+ name: __props.icon,
1177
+ class: "size-20 text-highlighted/75"
1178
+ }, null, _parent));
1179
+ _push(`<p class="text-lg font-mono font-medium text-highlighted">${ssrInterpolate(unref(display))}</p><p class="text-xs text-dimmed">${ssrInterpolate(__props.hint)}</p></div>`);
1180
+ };
1181
+ }
1182
+ });
1183
+ //#endregion
1184
+ //#region app/components/base/loading/phrases.vue
1185
+ var _sfc_setup$4 = phrases_vue_vue_type_script_setup_true_lang_default.setup;
1186
+ phrases_vue_vue_type_script_setup_true_lang_default.setup = (props, ctx) => {
1187
+ const ssrContext = useSSRContext();
1188
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/base/loading/phrases.vue");
1189
+ return _sfc_setup$4 ? _sfc_setup$4(props, ctx) : void 0;
1190
+ };
1191
+ var phrases_default = Object.assign(phrases_vue_vue_type_script_setup_true_lang_default, { __name: "BaseLoadingPhrases" });
1192
+ //#endregion
1193
+ //#region app/components/scenario/review/loading.vue?vue&type=script&setup=true&lang.ts
1194
+ var loading_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
1195
+ __name: "loading",
1196
+ __ssrInlineRender: true,
1197
+ props: { auth: {
1198
+ type: Boolean,
1199
+ default: false
1200
+ } },
1201
+ setup(__props) {
1202
+ const SCENARIO_PHRASES = [
1203
+ "Analisando os elementos da tela",
1204
+ "Identificando os fluxos de navegação",
1205
+ "Interpretando suas interações",
1206
+ "Gerando os contextos do cenário",
1207
+ "Escrevendo os passos em Gherkin",
1208
+ "Traduzindo para o teste Playwright",
1209
+ "Dando os retoques finais"
1210
+ ];
1211
+ const AUTH_PHRASES = [
1212
+ "Analisando os eventos gravados",
1213
+ "Identificando os campos de usuário e senha",
1214
+ "Escrevendo o fluxo de autenticação"
1215
+ ];
1216
+ return (_ctx, _push, _parent, _attrs) => {
1217
+ _push(ssrRenderComponent(phrases_default, mergeProps({
1218
+ phrases: __props.auth ? AUTH_PHRASES : SCENARIO_PHRASES,
1219
+ "data-testid": __props.auth ? "auth-carregando" : "contexto-carregando"
1220
+ }, _attrs), null, _parent));
1221
+ };
1222
+ }
1223
+ });
1224
+ //#endregion
1225
+ //#region app/components/scenario/review/loading.vue
1226
+ var _sfc_setup$3 = loading_vue_vue_type_script_setup_true_lang_default.setup;
1227
+ loading_vue_vue_type_script_setup_true_lang_default.setup = (props, ctx) => {
1228
+ const ssrContext = useSSRContext();
1229
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/scenario/review/loading.vue");
1230
+ return _sfc_setup$3 ? _sfc_setup$3(props, ctx) : void 0;
1231
+ };
1232
+ var loading_default = Object.assign(loading_vue_vue_type_script_setup_true_lang_default, { __name: "ScenarioReviewLoading" });
1233
+ //#endregion
1234
+ //#region app/composables/webdriver.ts
1235
+ var socket = null;
1236
+ function useWebdriver() {
1237
+ const state = useState("webdriver", () => ({
1238
+ connected: false,
1239
+ extensionReady: false,
1240
+ recording: false,
1241
+ replaying: false,
1242
+ replayFailedStep: null,
1243
+ error: null,
1244
+ events: [],
1245
+ videoSessionId: null,
1246
+ recordingStartedAt: null,
1247
+ storageState: null
1248
+ }));
1249
+ const url = "";
1250
+ function send(type, payload = {}) {
1251
+ if (void 0 === WebSocket.OPEN) socket.send(JSON.stringify({
1252
+ type,
1253
+ ...payload
1254
+ }));
1255
+ }
1256
+ function ensureConnected() {}
1257
+ function startRecording(mode = "scenario", options = {}) {
1258
+ state.value.error = null;
1259
+ state.value.events = options.replay ?? [];
1260
+ state.value.videoSessionId = null;
1261
+ state.value.storageState = null;
1262
+ state.value.recording = true;
1263
+ state.value.replaying = (options.replay?.length ?? 0) > 0;
1264
+ state.value.replayFailedStep = null;
1265
+ send("START_RECORDING", {
1266
+ mode,
1267
+ ...options
1268
+ });
1269
+ }
1270
+ function stopRecording() {
1271
+ send("STOP_RECORDING");
1272
+ state.value.recording = false;
1273
+ }
1274
+ return {
1275
+ state,
1276
+ url,
1277
+ ensureConnected,
1278
+ startRecording,
1279
+ stopRecording
1280
+ };
1281
+ }
1282
+ //#endregion
1283
+ //#region app/components/scenario/review/modal.vue?vue&type=script&setup=true&lang.ts
1284
+ var modal_vue_vue_type_script_setup_true_lang_default$1 = /*@__PURE__*/ defineComponent({
1285
+ __name: "modal",
1286
+ __ssrInlineRender: true,
1287
+ props: /*@__PURE__*/ mergeModels({
1288
+ slug: {},
1289
+ isPublic: {
1290
+ type: Boolean,
1291
+ default: false
1292
+ },
1293
+ scenario: { default: null }
1294
+ }, {
1295
+ "open": {
1296
+ type: Boolean,
1297
+ default: false
1298
+ },
1299
+ "openModifiers": {}
1300
+ }),
1301
+ emits: /*@__PURE__*/ mergeModels([
1302
+ "generated",
1303
+ "rerecord",
1304
+ "resume"
1305
+ ], ["update:open"]),
1306
+ setup(__props, { emit: __emit }) {
1307
+ const open = useModel(__props, "open");
1308
+ const emit = __emit;
1309
+ const isAuth = computed(() => __props.scenario?.is_auth === true);
1310
+ const scenarioId = computed(() => __props.scenario.spec.replace(/^tests\//, "").replace(/\.(spec|setup)\.ts$/, ""));
1311
+ const { state, url } = useWebdriver();
1312
+ function emptyDraft() {
1313
+ return {
1314
+ title: "",
1315
+ tags: [],
1316
+ domain: "",
1317
+ path: "",
1318
+ gherkin: "",
1319
+ playwright: ""
1320
+ };
1321
+ }
1322
+ const step = ref("review");
1323
+ const draft = ref(emptyDraft());
1324
+ const error = ref(null);
1325
+ watch(open, (isOpen) => {
1326
+ if (isOpen) {
1327
+ step.value = "review";
1328
+ draft.value = emptyDraft();
1329
+ error.value = null;
1330
+ }
1331
+ });
1332
+ const modalTitle = computed(() => {
1333
+ if (step.value === "edit") return "Revise os contextos";
1334
+ if (isAuth.value) return "Revise a gravação do login";
1335
+ return __props.scenario ? "Revise a gravação retomada" : "Revise seus eventos";
1336
+ });
1337
+ const generateLabel = computed(() => isAuth.value ? "Gerar autenticação" : "Gerar cenário");
1338
+ const timeline = computed(() => state.value.events.filter((event) => event.type && event.timestamp).sort((a, b) => a.timestamp - b.timestamp));
1339
+ const submitting = ref(false);
1340
+ const baseUrl = computed(() => {
1341
+ const first = timeline.value.find((event) => event.url);
1342
+ if (!first?.url) return null;
1343
+ try {
1344
+ return new URL(first.url).origin;
1345
+ } catch {
1346
+ return null;
1347
+ }
1348
+ });
1349
+ const mappedEvents = computed(() => toRecordedEvents(timeline.value));
1350
+ /** A autenticação não tem contexto para revisar: sai da revisão direto para o auth.setup.ts. */
1351
+ async function recordAuth() {
1352
+ try {
1353
+ const generated = await $fetch$2(`/api/projects/${__props.slug}/auth/record`, {
1354
+ method: "POST",
1355
+ body: {
1356
+ baseUrl: baseUrl.value,
1357
+ events: mappedEvents.value
1358
+ }
1359
+ });
1360
+ open.value = false;
1361
+ emit("generated", generated);
1362
+ } catch (err) {
1363
+ console.error("Falha ao gravar a autenticação:", err);
1364
+ error.value = extractServerError(err, "Não foi possível gerar a autenticação a partir da gravação.");
1365
+ step.value = "review";
1366
+ }
1367
+ }
1368
+ async function generate() {
1369
+ if (!baseUrl.value) {
1370
+ error.value = "Nenhuma navegação registrada na gravação.";
1371
+ return;
1372
+ }
1373
+ error.value = null;
1374
+ step.value = "loading";
1375
+ if (isAuth.value) return recordAuth();
1376
+ try {
1377
+ const generated = await $fetch$2(`/api/projects/${__props.slug}/tests/draft`, {
1378
+ method: "POST",
1379
+ body: {
1380
+ baseUrl: baseUrl.value,
1381
+ events: mappedEvents.value,
1382
+ isPublic: __props.isPublic
1383
+ }
1384
+ });
1385
+ draft.value = __props.scenario ? {
1386
+ ...generated,
1387
+ title: __props.scenario.title,
1388
+ path: scenarioId.value,
1389
+ domain: __props.scenario.domain ?? ""
1390
+ } : generated;
1391
+ step.value = "edit";
1392
+ } catch (err) {
1393
+ error.value = extractServerError(err, "Não foi possível gerar o cenário. Tente novamente.");
1394
+ step.value = "review";
1395
+ }
1396
+ }
1397
+ async function commit() {
1398
+ if (!draft.value) return;
1399
+ submitting.value = true;
1400
+ error.value = null;
1401
+ try {
1402
+ const saved = await $fetch$2(__props.scenario ? `/api/projects/${__props.slug}/scenarios/${scenarioId.value}` : `/api/projects/${__props.slug}/tests`, {
1403
+ method: __props.scenario ? "PATCH" : "POST",
1404
+ body: {
1405
+ ...draft.value,
1406
+ events: mappedEvents.value
1407
+ }
1408
+ });
1409
+ open.value = false;
1410
+ emit("generated", saved);
1411
+ } catch (err) {
1412
+ error.value = extractServerError(err, "Não foi possível salvar o cenário. Tente novamente.");
1413
+ } finally {
1414
+ submitting.value = false;
1415
+ }
1416
+ }
1417
+ function rerecord() {
1418
+ open.value = false;
1419
+ emit("rerecord");
1420
+ }
1421
+ /** Retomar do passo escolhido mantém o que veio antes dele e descarta ele e os seguintes. */
1422
+ function resume(index) {
1423
+ open.value = false;
1424
+ emit("resume", timeline.value.slice(0, index));
1425
+ }
1426
+ return (_ctx, _push, _parent, _attrs) => {
1427
+ const _component_BaseModal = modal_default$2;
1428
+ const _component_ScenarioReviewLoading = loading_default;
1429
+ const _component_ScenarioWarnings = warnings_default;
1430
+ const _component_ScenarioReviewContexts = contexts_default;
1431
+ const _component_ScenarioReviewTimeline = timeline_default;
1432
+ const _component_UAlert = _sfc_main;
1433
+ const _component_UButton = _sfc_main$3;
1434
+ _push(ssrRenderComponent(_component_BaseModal, mergeProps({
1435
+ open: open.value,
1436
+ "onUpdate:open": ($event) => open.value = $event,
1437
+ title: unref(modalTitle),
1438
+ dismissable: false,
1439
+ loading: unref(step) === "loading",
1440
+ wide: ""
1441
+ }, _attrs), {
1442
+ body: withCtx((_, _push, _parent, _scopeId) => {
1443
+ if (_push) {
1444
+ if (unref(step) === "loading") _push(ssrRenderComponent(_component_ScenarioReviewLoading, { auth: unref(isAuth) }, null, _parent, _scopeId));
1445
+ else if (unref(step) === "edit") {
1446
+ _push(`<!--[-->`);
1447
+ _push(ssrRenderComponent(_component_ScenarioWarnings, {
1448
+ warnings: unref(draft).warnings,
1449
+ slug: __props.slug,
1450
+ class: "mb-4"
1451
+ }, null, _parent, _scopeId));
1452
+ _push(ssrRenderComponent(_component_ScenarioReviewContexts, {
1453
+ draft: unref(draft),
1454
+ "onUpdate:draft": ($event) => isRef(draft) ? draft.value = $event : null,
1455
+ novo: ""
1456
+ }, null, _parent, _scopeId));
1457
+ _push(`<!--]-->`);
1458
+ } else _push(ssrRenderComponent(_component_ScenarioReviewTimeline, {
1459
+ events: unref(timeline),
1460
+ "video-src": unref(state).videoSessionId ? `${unref(url)}/recording/${unref(state).videoSessionId}` : null,
1461
+ "recording-started-at": unref(state).recordingStartedAt,
1462
+ resumable: "",
1463
+ onResume: resume
1464
+ }, null, _parent, _scopeId));
1465
+ if (unref(error)) _push(ssrRenderComponent(_component_UAlert, {
1466
+ color: "error",
1467
+ variant: "soft",
1468
+ description: unref(error),
1469
+ class: "mt-4",
1470
+ "data-testid": "revisao-erro"
1471
+ }, null, _parent, _scopeId));
1472
+ else _push(`<!---->`);
1473
+ } else return [unref(step) === "loading" ? (openBlock(), createBlock(_component_ScenarioReviewLoading, {
1474
+ key: 0,
1475
+ auth: unref(isAuth)
1476
+ }, null, 8, ["auth"])) : unref(step) === "edit" ? (openBlock(), createBlock(Fragment, { key: 1 }, [createVNode(_component_ScenarioWarnings, {
1477
+ warnings: unref(draft).warnings,
1478
+ slug: __props.slug,
1479
+ class: "mb-4"
1480
+ }, null, 8, ["warnings", "slug"]), createVNode(_component_ScenarioReviewContexts, {
1481
+ draft: unref(draft),
1482
+ "onUpdate:draft": ($event) => isRef(draft) ? draft.value = $event : null,
1483
+ novo: ""
1484
+ }, null, 8, ["draft", "onUpdate:draft"])], 64)) : (openBlock(), createBlock(_component_ScenarioReviewTimeline, {
1485
+ key: 2,
1486
+ events: unref(timeline),
1487
+ "video-src": unref(state).videoSessionId ? `${unref(url)}/recording/${unref(state).videoSessionId}` : null,
1488
+ "recording-started-at": unref(state).recordingStartedAt,
1489
+ resumable: "",
1490
+ onResume: resume
1491
+ }, null, 8, [
1492
+ "events",
1493
+ "video-src",
1494
+ "recording-started-at"
1495
+ ])), unref(error) ? (openBlock(), createBlock(_component_UAlert, {
1496
+ key: 3,
1497
+ color: "error",
1498
+ variant: "soft",
1499
+ description: unref(error),
1500
+ class: "mt-4",
1501
+ "data-testid": "revisao-erro"
1502
+ }, null, 8, ["description"])) : createCommentVNode("", true)];
1503
+ }),
1504
+ footer: withCtx((_, _push, _parent, _scopeId) => {
1505
+ if (_push) {
1506
+ if (unref(step) === "edit") {
1507
+ _push(`<!--[-->`);
1508
+ _push(ssrRenderComponent(_component_UButton, {
1509
+ label: "Cancelar",
1510
+ color: "neutral",
1511
+ variant: "ghost",
1512
+ "data-testid": "contexto-cancelar",
1513
+ onClick: ($event) => open.value = false
1514
+ }, null, _parent, _scopeId));
1515
+ _push(ssrRenderComponent(_component_UButton, {
1516
+ label: "Enviar",
1517
+ loading: unref(submitting),
1518
+ "data-testid": "contexto-enviar",
1519
+ onClick: commit
1520
+ }, null, _parent, _scopeId));
1521
+ _push(`<!--]-->`);
1522
+ } else {
1523
+ _push(`<!--[-->`);
1524
+ _push(ssrRenderComponent(_component_UButton, {
1525
+ label: "Gravar novamente",
1526
+ color: "neutral",
1527
+ variant: "soft",
1528
+ class: "mr-auto",
1529
+ "data-testid": "revisao-regravar",
1530
+ onClick: rerecord
1531
+ }, null, _parent, _scopeId));
1532
+ _push(ssrRenderComponent(_component_UButton, {
1533
+ label: "Cancelar",
1534
+ color: "neutral",
1535
+ variant: "ghost",
1536
+ "data-testid": "revisao-cancelar",
1537
+ onClick: ($event) => open.value = false
1538
+ }, null, _parent, _scopeId));
1539
+ _push(ssrRenderComponent(_component_UButton, {
1540
+ label: unref(generateLabel),
1541
+ "data-testid": "revisao-gerar",
1542
+ onClick: generate
1543
+ }, null, _parent, _scopeId));
1544
+ _push(`<!--]-->`);
1545
+ }
1546
+ } else return [unref(step) === "edit" ? (openBlock(), createBlock(Fragment, { key: 0 }, [createVNode(_component_UButton, {
1547
+ label: "Cancelar",
1548
+ color: "neutral",
1549
+ variant: "ghost",
1550
+ "data-testid": "contexto-cancelar",
1551
+ onClick: ($event) => open.value = false
1552
+ }, null, 8, ["onClick"]), createVNode(_component_UButton, {
1553
+ label: "Enviar",
1554
+ loading: unref(submitting),
1555
+ "data-testid": "contexto-enviar",
1556
+ onClick: commit
1557
+ }, null, 8, ["loading"])], 64)) : (openBlock(), createBlock(Fragment, { key: 1 }, [
1558
+ createVNode(_component_UButton, {
1559
+ label: "Gravar novamente",
1560
+ color: "neutral",
1561
+ variant: "soft",
1562
+ class: "mr-auto",
1563
+ "data-testid": "revisao-regravar",
1564
+ onClick: rerecord
1565
+ }),
1566
+ createVNode(_component_UButton, {
1567
+ label: "Cancelar",
1568
+ color: "neutral",
1569
+ variant: "ghost",
1570
+ "data-testid": "revisao-cancelar",
1571
+ onClick: ($event) => open.value = false
1572
+ }, null, 8, ["onClick"]),
1573
+ createVNode(_component_UButton, {
1574
+ label: unref(generateLabel),
1575
+ "data-testid": "revisao-gerar",
1576
+ onClick: generate
1577
+ }, null, 8, ["label"])
1578
+ ], 64))];
1579
+ }),
1580
+ _: 1
1581
+ }, _parent));
1582
+ };
1583
+ }
1584
+ });
1585
+ //#endregion
1586
+ //#region app/components/scenario/review/modal.vue
1587
+ var _sfc_setup$2 = modal_vue_vue_type_script_setup_true_lang_default$1.setup;
1588
+ modal_vue_vue_type_script_setup_true_lang_default$1.setup = (props, ctx) => {
1589
+ const ssrContext = useSSRContext();
1590
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/scenario/review/modal.vue");
1591
+ return _sfc_setup$2 ? _sfc_setup$2(props, ctx) : void 0;
1592
+ };
1593
+ var modal_default$1 = Object.assign(modal_vue_vue_type_script_setup_true_lang_default$1, { __name: "ScenarioReviewModal" });
1594
+ //#endregion
1595
+ //#region app/components/scenario/test-run/steps.vue?vue&type=script&setup=true&lang.ts
1596
+ var steps_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
1597
+ __name: "steps",
1598
+ __ssrInlineRender: true,
1599
+ props: { steps: { default: () => [] } },
1600
+ setup(__props) {
1601
+ const stepIcons = {
1602
+ waiting: "i-ic-round-radio-button-unchecked",
1603
+ running: "line-md:loading-twotone-loop",
1604
+ success: "i-ic-round-check-circle",
1605
+ failed: "i-ic-round-error"
1606
+ };
1607
+ const stepColors = {
1608
+ waiting: "text-dimmed",
1609
+ running: "text-neutral",
1610
+ success: "text-success",
1611
+ failed: "text-error"
1612
+ };
1613
+ return (_ctx, _push, _parent, _attrs) => {
1614
+ const _component_UIcon = _sfc_main$8;
1615
+ _push(`<ol${ssrRenderAttrs(mergeProps({ class: "flex flex-col" }, _attrs))}><!--[-->`);
1616
+ ssrRenderList(__props.steps, (step, i) => {
1617
+ _push(`<li data-testid="execucao-step"${ssrRenderAttr("data-status", step.status)} class="flex items-stretch gap-3 pb-4 last:pb-0"><div class="flex flex-col items-center">`);
1618
+ _push(ssrRenderComponent(_component_UIcon, {
1619
+ name: stepIcons[step.status],
1620
+ class: ["size-6 shrink-0 transition-colors", stepColors[step.status]]
1621
+ }, null, _parent));
1622
+ if (i < __props.steps.length - 1) _push(`<span class="w-px grow min-h-4 -mb-4 bg-inverted/30"></span>`);
1623
+ else _push(`<!---->`);
1624
+ _push(`</div><div class="min-w-0"><p class="text-base" data-testid="execucao-step-titulo">${ssrInterpolate(step.title)}</p>`);
1625
+ if (step.status === "failed" && step.error) _push(`<p class="text-sm text-dimmed mt-1" data-testid="execucao-step-erro"><span class="font-semibold text-error">Erro:</span> ${ssrInterpolate(step.error)}</p>`);
1626
+ else _push(`<!---->`);
1627
+ _push(`</div></li>`);
1628
+ });
1629
+ _push(`<!--]--></ol>`);
1630
+ };
1631
+ }
1632
+ });
1633
+ //#endregion
1634
+ //#region app/components/scenario/test-run/steps.vue
1635
+ var _sfc_setup$1 = steps_vue_vue_type_script_setup_true_lang_default.setup;
1636
+ steps_vue_vue_type_script_setup_true_lang_default.setup = (props, ctx) => {
1637
+ const ssrContext = useSSRContext();
1638
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/scenario/test-run/steps.vue");
1639
+ return _sfc_setup$1 ? _sfc_setup$1(props, ctx) : void 0;
1640
+ };
1641
+ var steps_default = Object.assign(steps_vue_vue_type_script_setup_true_lang_default, { __name: "ScenarioTestRunSteps" });
1642
+ //#endregion
1643
+ //#region app/components/scenario/test-run/modal.vue?vue&type=script&setup=true&lang.ts
1644
+ var modal_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
1645
+ __name: "modal",
1646
+ __ssrInlineRender: true,
1647
+ props: /*@__PURE__*/ mergeModels({
1648
+ running: {
1649
+ type: Boolean,
1650
+ default: false
1651
+ },
1652
+ passed: {
1653
+ type: Boolean,
1654
+ default: false
1655
+ },
1656
+ steps: { default: () => [] },
1657
+ videoUrl: { default: null },
1658
+ projectName: {},
1659
+ scenarioName: {},
1660
+ branch: { default: null },
1661
+ testedAt: { default: null },
1662
+ playwright: { default: null },
1663
+ output: { default: null },
1664
+ kind: { default: "cenario" }
1665
+ }, {
1666
+ "open": {
1667
+ type: Boolean,
1668
+ default: false
1669
+ },
1670
+ "openModifiers": {}
1671
+ }),
1672
+ emits: /*@__PURE__*/ mergeModels(["fix"], ["update:open"]),
1673
+ setup(__props, { emit: __emit }) {
1674
+ const emit = __emit;
1675
+ const open = useModel(__props, "open");
1676
+ const { configured: aiConfigured } = useAi();
1677
+ const isAuth = computed(() => __props.kind === "autenticacao");
1678
+ const label = computed(() => isAuth.value ? "Autenticação" : "Cenário");
1679
+ const runningTitle = computed(() => isAuth.value ? "Testando autenticação..." : "Testando cenário...");
1680
+ const resultTitle = computed(() => isAuth.value ? "Resultado da autenticação" : "Resultado do teste");
1681
+ const failedStep = computed(() => __props.steps.findIndex((step) => step.status === "failed"));
1682
+ function seekToPreviewFrame(event) {
1683
+ const video = event.target;
1684
+ video.currentTime = video.duration * .25;
1685
+ }
1686
+ return (_ctx, _push, _parent, _attrs) => {
1687
+ const _component_BaseModal = modal_default$2;
1688
+ const _component_UBadge = _sfc_main$2;
1689
+ const _component_UTooltip = _sfc_main$7;
1690
+ const _component_UButton = _sfc_main$3;
1691
+ const _component_BaseLoadingPhrases = phrases_default;
1692
+ const _component_UAlert = _sfc_main;
1693
+ const _component_ScenarioTestRunSteps = steps_default;
1694
+ const _component_BaseCodefield = codefield_default;
1695
+ _push(ssrRenderComponent(_component_BaseModal, mergeProps({
1696
+ open: open.value,
1697
+ "onUpdate:open": ($event) => open.value = $event,
1698
+ dismissable: !__props.running,
1699
+ wide: ""
1700
+ }, _attrs), createSlots({
1701
+ header: withCtx((_, _push, _parent, _scopeId) => {
1702
+ if (_push) {
1703
+ _push(`<div class="flex w-full items-start justify-between gap-4"${_scopeId}><div class="flex flex-col pt-6 gap-2"${_scopeId}>`);
1704
+ if (__props.running) _push(`<p class="text-xl font-bold"${_scopeId}>${ssrInterpolate(unref(runningTitle))}</p>`);
1705
+ else {
1706
+ _push(`<!--[-->`);
1707
+ _push(ssrRenderComponent(_component_UBadge, {
1708
+ class: "self-start",
1709
+ color: __props.passed ? "success" : "error",
1710
+ icon: __props.passed ? "i-ic-round-check-circle" : "i-ic-round-error",
1711
+ label: __props.passed ? "Sucesso" : "Falha",
1712
+ "data-testid": "execucao-status"
1713
+ }, null, _parent, _scopeId));
1714
+ _push(`<p class="mt-2 text-xl font-bold"${_scopeId}>${ssrInterpolate(unref(resultTitle))}</p><!--]-->`);
1715
+ }
1716
+ _push(`</div>`);
1717
+ if (!__props.running && !__props.passed && unref(failedStep) !== -1) _push(ssrRenderComponent(_component_UTooltip, {
1718
+ text: unref(AI_OFF_HINT),
1719
+ disabled: unref(aiConfigured),
1720
+ "delay-duration": 0,
1721
+ arrow: ""
1722
+ }, {
1723
+ default: withCtx((_, _push, _parent, _scopeId) => {
1724
+ if (_push) {
1725
+ _push(`<span class="mt-6 shrink-0"${_scopeId}>`);
1726
+ _push(ssrRenderComponent(_component_UButton, {
1727
+ label: "Corrigir",
1728
+ "trailing-icon": "i-ic-round-auto-awesome",
1729
+ disabled: !unref(aiConfigured),
1730
+ class: unref(aiConfigured) ? "" : "pointer-events-none",
1731
+ "data-testid": "execucao-corrigir",
1732
+ onClick: ($event) => emit("fix")
1733
+ }, null, _parent, _scopeId));
1734
+ _push(`</span>`);
1735
+ } else return [createVNode("span", { class: "mt-6 shrink-0" }, [createVNode(_component_UButton, {
1736
+ label: "Corrigir",
1737
+ "trailing-icon": "i-ic-round-auto-awesome",
1738
+ disabled: !unref(aiConfigured),
1739
+ class: unref(aiConfigured) ? "" : "pointer-events-none",
1740
+ "data-testid": "execucao-corrigir",
1741
+ onClick: ($event) => emit("fix")
1742
+ }, null, 8, [
1743
+ "disabled",
1744
+ "class",
1745
+ "onClick"
1746
+ ])])];
1747
+ }),
1748
+ _: 1
1749
+ }, _parent, _scopeId));
1750
+ else _push(`<!---->`);
1751
+ _push(`</div>`);
1752
+ } else return [createVNode("div", { class: "flex w-full items-start justify-between gap-4" }, [createVNode("div", { class: "flex flex-col pt-6 gap-2" }, [__props.running ? (openBlock(), createBlock("p", {
1753
+ key: 0,
1754
+ class: "text-xl font-bold"
1755
+ }, toDisplayString(unref(runningTitle)), 1)) : (openBlock(), createBlock(Fragment, { key: 1 }, [createVNode(_component_UBadge, {
1756
+ class: "self-start",
1757
+ color: __props.passed ? "success" : "error",
1758
+ icon: __props.passed ? "i-ic-round-check-circle" : "i-ic-round-error",
1759
+ label: __props.passed ? "Sucesso" : "Falha",
1760
+ "data-testid": "execucao-status"
1761
+ }, null, 8, [
1762
+ "color",
1763
+ "icon",
1764
+ "label"
1765
+ ]), createVNode("p", { class: "mt-2 text-xl font-bold" }, toDisplayString(unref(resultTitle)), 1)], 64))]), !__props.running && !__props.passed && unref(failedStep) !== -1 ? (openBlock(), createBlock(_component_UTooltip, {
1766
+ key: 0,
1767
+ text: unref(AI_OFF_HINT),
1768
+ disabled: unref(aiConfigured),
1769
+ "delay-duration": 0,
1770
+ arrow: ""
1771
+ }, {
1772
+ default: withCtx(() => [createVNode("span", { class: "mt-6 shrink-0" }, [createVNode(_component_UButton, {
1773
+ label: "Corrigir",
1774
+ "trailing-icon": "i-ic-round-auto-awesome",
1775
+ disabled: !unref(aiConfigured),
1776
+ class: unref(aiConfigured) ? "" : "pointer-events-none",
1777
+ "data-testid": "execucao-corrigir",
1778
+ onClick: ($event) => emit("fix")
1779
+ }, null, 8, [
1780
+ "disabled",
1781
+ "class",
1782
+ "onClick"
1783
+ ])])]),
1784
+ _: 1
1785
+ }, 8, ["text", "disabled"])) : createCommentVNode("", true)])];
1786
+ }),
1787
+ body: withCtx((_, _push, _parent, _scopeId) => {
1788
+ if (_push) {
1789
+ if (__props.running && __props.steps.length === 0) _push(ssrRenderComponent(_component_BaseLoadingPhrases, {
1790
+ phrases: ["Iniciando a execução"],
1791
+ "data-testid": "execucao-iniciando"
1792
+ }, null, _parent, _scopeId));
1793
+ else {
1794
+ _push(`<!--[-->`);
1795
+ if (!__props.running) {
1796
+ _push(`<div class="mb-6 space-y-0.5 text-sm" data-testid="execucao-detalhes"${_scopeId}><p${_scopeId}><span class="font-semibold"${_scopeId}>Projeto:</span> ${ssrInterpolate(__props.projectName)}</p><p${_scopeId}><span class="font-semibold"${_scopeId}>${ssrInterpolate(unref(label))}:</span> ${ssrInterpolate(__props.scenarioName)}</p>`);
1797
+ if (__props.branch) _push(`<p${_scopeId}><span class="font-semibold"${_scopeId}>Branch:</span> ${ssrInterpolate(__props.branch)}</p>`);
1798
+ else _push(`<!---->`);
1799
+ if (__props.testedAt) _push(`<p${_scopeId}><span class="font-semibold"${_scopeId}>Testado em:</span> ${ssrInterpolate(__props.testedAt)}</p>`);
1800
+ else _push(`<!---->`);
1801
+ _push(`</div>`);
1802
+ } else _push(`<!---->`);
1803
+ if (__props.videoUrl) _push(`<video${ssrRenderAttr("src", __props.videoUrl)} preload="metadata" controls class="mx-auto mb-6 w-3/4 rounded-lg bg-elevated" data-testid="execucao-video"${_scopeId}></video>`);
1804
+ else _push(`<!---->`);
1805
+ if (__props.output) _push(ssrRenderComponent(_component_UAlert, {
1806
+ color: "error",
1807
+ variant: "soft",
1808
+ icon: "i-ic-round-error",
1809
+ title: "A execução não chegou a começar",
1810
+ class: "mb-6",
1811
+ "data-testid": "execucao-saida"
1812
+ }, {
1813
+ description: withCtx((_, _push, _parent, _scopeId) => {
1814
+ if (_push) _push(`<p class="mb-2"${_scopeId}> O Playwright encerrou antes de rodar qualquer passo. Saída do runner: </p><code class="block whitespace-pre-wrap font-mono text-xs"${_scopeId}>${ssrInterpolate(__props.output)}</code>`);
1815
+ else return [createVNode("p", { class: "mb-2" }, " O Playwright encerrou antes de rodar qualquer passo. Saída do runner: "), createVNode("code", { class: "block whitespace-pre-wrap font-mono text-xs" }, toDisplayString(__props.output), 1)];
1816
+ }),
1817
+ _: 1
1818
+ }, _parent, _scopeId));
1819
+ else _push(`<!---->`);
1820
+ if (__props.steps.length) _push(`<p class="mb-3 text-lg font-semibold"${_scopeId}> Timeline de eventos </p>`);
1821
+ else _push(`<!---->`);
1822
+ _push(ssrRenderComponent(_component_ScenarioTestRunSteps, { steps: __props.steps }, null, _parent, _scopeId));
1823
+ if (__props.playwright) {
1824
+ _push(`<!--[--><p class="mt-6 mb-3 text-lg font-semibold"${_scopeId}> Código executado </p>`);
1825
+ _push(ssrRenderComponent(_component_BaseCodefield, {
1826
+ "model-value": __props.playwright,
1827
+ language: "typescript",
1828
+ readonly: "",
1829
+ testid: "execucao-playwright"
1830
+ }, null, _parent, _scopeId));
1831
+ _push(`<!--]-->`);
1832
+ } else _push(`<!---->`);
1833
+ _push(`<!--]-->`);
1834
+ }
1835
+ } else return [__props.running && __props.steps.length === 0 ? (openBlock(), createBlock(_component_BaseLoadingPhrases, {
1836
+ key: 0,
1837
+ phrases: ["Iniciando a execução"],
1838
+ "data-testid": "execucao-iniciando"
1839
+ })) : (openBlock(), createBlock(Fragment, { key: 1 }, [
1840
+ !__props.running ? (openBlock(), createBlock("div", {
1841
+ key: 0,
1842
+ class: "mb-6 space-y-0.5 text-sm",
1843
+ "data-testid": "execucao-detalhes"
1844
+ }, [
1845
+ createVNode("p", null, [createVNode("span", { class: "font-semibold" }, "Projeto:"), createTextVNode(" " + toDisplayString(__props.projectName), 1)]),
1846
+ createVNode("p", null, [createVNode("span", { class: "font-semibold" }, toDisplayString(unref(label)) + ":", 1), createTextVNode(" " + toDisplayString(__props.scenarioName), 1)]),
1847
+ __props.branch ? (openBlock(), createBlock("p", { key: 0 }, [createVNode("span", { class: "font-semibold" }, "Branch:"), createTextVNode(" " + toDisplayString(__props.branch), 1)])) : createCommentVNode("", true),
1848
+ __props.testedAt ? (openBlock(), createBlock("p", { key: 1 }, [createVNode("span", { class: "font-semibold" }, "Testado em:"), createTextVNode(" " + toDisplayString(__props.testedAt), 1)])) : createCommentVNode("", true)
1849
+ ])) : createCommentVNode("", true),
1850
+ __props.videoUrl ? (openBlock(), createBlock("video", {
1851
+ key: 1,
1852
+ src: __props.videoUrl,
1853
+ preload: "metadata",
1854
+ controls: "",
1855
+ class: "mx-auto mb-6 w-3/4 rounded-lg bg-elevated",
1856
+ "data-testid": "execucao-video",
1857
+ onLoadedmetadata: seekToPreviewFrame
1858
+ }, null, 40, ["src"])) : createCommentVNode("", true),
1859
+ __props.output ? (openBlock(), createBlock(_component_UAlert, {
1860
+ key: 2,
1861
+ color: "error",
1862
+ variant: "soft",
1863
+ icon: "i-ic-round-error",
1864
+ title: "A execução não chegou a começar",
1865
+ class: "mb-6",
1866
+ "data-testid": "execucao-saida"
1867
+ }, {
1868
+ description: withCtx(() => [createVNode("p", { class: "mb-2" }, " O Playwright encerrou antes de rodar qualquer passo. Saída do runner: "), createVNode("code", { class: "block whitespace-pre-wrap font-mono text-xs" }, toDisplayString(__props.output), 1)]),
1869
+ _: 1
1870
+ })) : createCommentVNode("", true),
1871
+ __props.steps.length ? (openBlock(), createBlock("p", {
1872
+ key: 3,
1873
+ class: "mb-3 text-lg font-semibold"
1874
+ }, " Timeline de eventos ")) : createCommentVNode("", true),
1875
+ createVNode(_component_ScenarioTestRunSteps, { steps: __props.steps }, null, 8, ["steps"]),
1876
+ __props.playwright ? (openBlock(), createBlock(Fragment, { key: 4 }, [createVNode("p", { class: "mt-6 mb-3 text-lg font-semibold" }, " Código executado "), createVNode(_component_BaseCodefield, {
1877
+ "model-value": __props.playwright,
1878
+ language: "typescript",
1879
+ readonly: "",
1880
+ testid: "execucao-playwright"
1881
+ }, null, 8, ["model-value"])], 64)) : createCommentVNode("", true)
1882
+ ], 64))];
1883
+ }),
1884
+ _: 2
1885
+ }, [!__props.running ? {
1886
+ name: "footer",
1887
+ fn: withCtx((_, _push, _parent, _scopeId) => {
1888
+ if (_push) _push(ssrRenderComponent(_component_UButton, {
1889
+ label: "Fechar",
1890
+ color: "neutral",
1891
+ variant: "ghost",
1892
+ "data-testid": "execucao-fechar",
1893
+ onClick: ($event) => open.value = false
1894
+ }, null, _parent, _scopeId));
1895
+ else return [createVNode(_component_UButton, {
1896
+ label: "Fechar",
1897
+ color: "neutral",
1898
+ variant: "ghost",
1899
+ "data-testid": "execucao-fechar",
1900
+ onClick: ($event) => open.value = false
1901
+ }, null, 8, ["onClick"])];
1902
+ }),
1903
+ key: "0"
1904
+ } : void 0]), _parent));
1905
+ };
1906
+ }
1907
+ });
1908
+ //#endregion
1909
+ //#region app/components/scenario/test-run/modal.vue
1910
+ var _sfc_setup = modal_vue_vue_type_script_setup_true_lang_default.setup;
1911
+ modal_vue_vue_type_script_setup_true_lang_default.setup = (props, ctx) => {
1912
+ const ssrContext = useSSRContext();
1913
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/scenario/test-run/modal.vue");
1914
+ return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
1915
+ };
1916
+ var modal_default = Object.assign(modal_vue_vue_type_script_setup_true_lang_default, { __name: "ScenarioTestRunModal" });
1917
+ //#endregion
1918
+ //#region app/composables/run-stream.ts
1919
+ /** O que o Playwright reporta por passo/teste, no vocabulário da timeline. */
1920
+ var STATUS = {
1921
+ pending: "running",
1922
+ success: "success",
1923
+ failed: "failed",
1924
+ skipped: "waiting"
1925
+ };
1926
+ function videoUrlFor(path) {
1927
+ return `/runner/video?${new URLSearchParams({ path })}`;
1928
+ }
1929
+ /** O relatório HTML da última execução do projeto, servido pelo backend com vídeo e trace dentro. */
1930
+ function reportUrlFor(slug) {
1931
+ return `/api/projects/${slug}/report/`;
1932
+ }
1933
+ function formatTestedAt(date) {
1934
+ return date.toLocaleString("pt-BR", {
1935
+ dateStyle: "short",
1936
+ timeStyle: "short"
1937
+ });
1938
+ }
1939
+ /** Execução de um spec pelo backend, com a timeline chegando passo a passo por SSE. */
1940
+ function useRunStream(slug) {
1941
+ const steps = ref([]);
1942
+ const ran = ref([]);
1943
+ const running = ref(false);
1944
+ const passed = ref(false);
1945
+ const videoUrl = ref(null);
1946
+ const testedAt = ref(null);
1947
+ const output = ref(null);
1948
+ /** A ordem é a que o teste declarou; o passo que ele nunca anunciou entra no fim, na chegada. */
1949
+ const tests = computed(() => ran.value.map((test) => ({
1950
+ ...test,
1951
+ steps: steps.value.map((step, arrival) => ({
1952
+ step,
1953
+ arrival
1954
+ })).filter(({ step }) => step.testId === test.id).sort((a, b) => (a.step.order ?? Infinity) - (b.step.order ?? Infinity) || a.arrival - b.arrival).map(({ step }) => step)
1955
+ })));
1956
+ function reset() {
1957
+ steps.value = [];
1958
+ ran.value = [];
1959
+ videoUrl.value = null;
1960
+ testedAt.value = null;
1961
+ output.value = null;
1962
+ passed.value = false;
1963
+ }
1964
+ /** O passo pertence ao teste do evento; a semente da timeline ainda não tem dono e serve a qualquer um. */
1965
+ function sameTest(step, event) {
1966
+ return !event.testId || !step.testId || step.testId === event.testId;
1967
+ }
1968
+ /** A timeline semeada pelo run inteiro não tem dono: o teste adota a que é dele antes de criar a sua. */
1969
+ function seed(testId, titles) {
1970
+ const seeded = [...steps.value];
1971
+ titles.forEach((title, order) => {
1972
+ const orphan = seeded.findIndex((step) => step.title === title && step.status === "waiting" && !step.testId);
1973
+ const step = {
1974
+ testId,
1975
+ order,
1976
+ title,
1977
+ status: "waiting"
1978
+ };
1979
+ if (orphan === -1) seeded.push(step);
1980
+ else seeded[orphan] = step;
1981
+ });
1982
+ steps.value = seeded;
1983
+ }
1984
+ function start({ spec, grep }, onFinish) {
1985
+ reset();
1986
+ running.value = true;
1987
+ const query = new URLSearchParams({
1988
+ ...spec ? { spec } : {},
1989
+ ...grep ? { grep } : {}
1990
+ });
1991
+ const source = new EventSource(`/api/projects/${slug()}/run-stream?${query}`);
1992
+ source.onmessage = (message) => {
1993
+ const data = JSON.parse(message.data);
1994
+ if (data.event === "run:started") steps.value = (data.steps ?? []).map((title) => ({
1995
+ title,
1996
+ status: "waiting"
1997
+ }));
1998
+ if (data.event === "step") {
1999
+ if (data.status === "pending") {
2000
+ const own = steps.value.findIndex((step) => step.title === data.title && step.status === "waiting" && step.testId === data.testId);
2001
+ const waiting = own !== -1 ? own : steps.value.findIndex((step) => step.title === data.title && step.status === "waiting" && sameTest(step, data));
2002
+ const seeded = waiting === -1 ? void 0 : steps.value[waiting];
2003
+ const step = {
2004
+ testId: data.testId,
2005
+ order: seeded?.order,
2006
+ title: data.title,
2007
+ status: "running"
2008
+ };
2009
+ if (waiting === -1) steps.value = [...steps.value, step];
2010
+ else steps.value[waiting] = step;
2011
+ return;
2012
+ }
2013
+ const running = steps.value.findLastIndex((step) => step.title === data.title && step.status === "running" && sameTest(step, data));
2014
+ const index = running !== -1 || data.status !== "failed" ? running : steps.value.findLastIndex((step) => step.title === data.title && step.status === "success" && sameTest(step, data));
2015
+ if (index !== -1) steps.value[index] = {
2016
+ testId: steps.value[index].testId ?? data.testId,
2017
+ order: steps.value[index].order,
2018
+ title: data.title,
2019
+ status: STATUS[data.status],
2020
+ error: data.error ?? null
2021
+ };
2022
+ }
2023
+ if (data.event === "test") {
2024
+ if (data.id) {
2025
+ if (!ran.value.some((previous) => previous.id === data.id) && data.steps?.length) seed(data.id, data.steps);
2026
+ const test = {
2027
+ id: data.id,
2028
+ title: data.title,
2029
+ status: STATUS[data.status],
2030
+ error: data.error ?? null
2031
+ };
2032
+ const known = ran.value.findIndex((previous) => previous.id === data.id);
2033
+ if (known === -1) ran.value = [...ran.value, test];
2034
+ else ran.value[known] = test;
2035
+ }
2036
+ if (data.status !== "pending" && data.videoPath) videoUrl.value = videoUrlFor(data.videoPath);
2037
+ }
2038
+ if (data.event === "run:finished") {
2039
+ source.close();
2040
+ running.value = false;
2041
+ passed.value = data.passed;
2042
+ output.value = data.output ?? null;
2043
+ testedAt.value = formatTestedAt(/* @__PURE__ */ new Date());
2044
+ onFinish?.();
2045
+ }
2046
+ };
2047
+ source.onerror = () => {
2048
+ source.close();
2049
+ running.value = false;
2050
+ testedAt.value = formatTestedAt(/* @__PURE__ */ new Date());
2051
+ if (steps.value.length === 0) steps.value = [{
2052
+ title: "Não foi possível executar o teste.",
2053
+ status: "failed"
2054
+ }];
2055
+ };
2056
+ }
2057
+ return {
2058
+ steps,
2059
+ tests,
2060
+ running,
2061
+ passed,
2062
+ videoUrl,
2063
+ testedAt,
2064
+ output,
2065
+ failedStep: computed(() => steps.value.find((step) => step.status === "failed")),
2066
+ start,
2067
+ reset
2068
+ };
2069
+ }
2070
+ //#endregion
2071
+ //#region app/utils/tags.ts
2072
+ function tagColor(tag) {
2073
+ if (tag === "@read") return "success";
2074
+ if (tag === "@write") return "warning";
2075
+ return "primary";
2076
+ }
2077
+
2078
+ export { _sfc_main as _, useWebdriver as a, timeline_default as b, codefield_default as c, confirm_default as d, empty_default as e, modal_default as f, formatTestedAt as g, draftFromScenario as h, contexts_default as i, steps_default as j, modal_default$1 as m, phrases_default as p, reportUrlFor as r, setup_default as s, tagColor as t, useRunStream as u, videoUrlFor as v, warnings_default as w };
2079
+ //# sourceMappingURL=tags-X7K7nkM2.mjs.map