@razohq/razo 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +176 -0
- package/dist/chunk-UCLP2ILU.mjs +20 -0
- package/dist/chunk-UCLP2ILU.mjs.map +1 -0
- package/dist/events-D_lCLx1V.d.mts +44 -0
- package/dist/events-D_lCLx1V.d.ts +44 -0
- package/dist/index.d.mts +336 -0
- package/dist/index.d.ts +336 -0
- package/dist/index.js +961 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +892 -0
- package/dist/index.mjs.map +1 -0
- package/dist/reporter.d.mts +31 -0
- package/dist/reporter.d.ts +31 -0
- package/dist/reporter.js +91 -0
- package/dist/reporter.js.map +1 -0
- package/dist/reporter.mjs +50 -0
- package/dist/reporter.mjs.map +1 -0
- package/dist/vite.d.mts +29 -0
- package/dist/vite.d.ts +29 -0
- package/dist/vite.js +55 -0
- package/dist/vite.js.map +1 -0
- package/dist/vite.mjs +26 -0
- package/dist/vite.mjs.map +1 -0
- package/package.json +110 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import { Page, Locator } from '@playwright/test';
|
|
2
|
+
export { A as AI_STEP_ATTACHMENT, S as StepEvent, e as emitStepEvent } from './events-D_lCLx1V.js';
|
|
3
|
+
|
|
4
|
+
interface SentenceContext {
|
|
5
|
+
controlType: string;
|
|
6
|
+
name: string;
|
|
7
|
+
detail?: string;
|
|
8
|
+
expected?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Sentence grammar: one fixed template per verb, in a single place,
|
|
12
|
+
* so the narration is predictable and parseable by an AI.
|
|
13
|
+
*/
|
|
14
|
+
declare const SENTENCES: {
|
|
15
|
+
readonly click: (c: SentenceContext) => string;
|
|
16
|
+
readonly fill: (c: SentenceContext) => string;
|
|
17
|
+
readonly clear: (c: SentenceContext) => string;
|
|
18
|
+
readonly select: (c: SentenceContext) => string;
|
|
19
|
+
readonly check: (c: SentenceContext) => string;
|
|
20
|
+
readonly uncheck: (c: SentenceContext) => string;
|
|
21
|
+
readonly choose: (c: SentenceContext) => string;
|
|
22
|
+
readonly 'choose-many': (c: SentenceContext) => string;
|
|
23
|
+
readonly open: (c: SentenceContext) => string;
|
|
24
|
+
readonly attach: (c: SentenceContext) => string;
|
|
25
|
+
readonly set: (c: SentenceContext) => string;
|
|
26
|
+
readonly 'assert-visible': (c: SentenceContext) => string;
|
|
27
|
+
readonly 'assert-enabled': (c: SentenceContext) => string;
|
|
28
|
+
readonly 'assert-disabled': (c: SentenceContext) => string;
|
|
29
|
+
readonly 'assert-text': (c: SentenceContext) => string;
|
|
30
|
+
readonly 'assert-checked': (c: SentenceContext) => string;
|
|
31
|
+
readonly 'assert-unchecked': (c: SentenceContext) => string;
|
|
32
|
+
readonly 'assert-selected': (c: SentenceContext) => string;
|
|
33
|
+
readonly 'assert-value': (c: SentenceContext) => string;
|
|
34
|
+
readonly 'assert-href': (c: SentenceContext) => string;
|
|
35
|
+
readonly hover: (c: SentenceContext) => string;
|
|
36
|
+
readonly 'double-click': (c: SentenceContext) => string;
|
|
37
|
+
readonly 'right-click': (c: SentenceContext) => string;
|
|
38
|
+
readonly press: (c: SentenceContext) => string;
|
|
39
|
+
readonly focus: (c: SentenceContext) => string;
|
|
40
|
+
readonly 'scroll-to': (c: SentenceContext) => string;
|
|
41
|
+
readonly drag: (c: SentenceContext) => string;
|
|
42
|
+
readonly 'assert-hidden': (c: SentenceContext) => string;
|
|
43
|
+
readonly 'assert-focused': (c: SentenceContext) => string;
|
|
44
|
+
readonly 'assert-contains-text': (c: SentenceContext) => string;
|
|
45
|
+
readonly 'assert-attribute': (c: SentenceContext) => string;
|
|
46
|
+
readonly 'assert-empty': (c: SentenceContext) => string;
|
|
47
|
+
readonly 'turn-on': (c: SentenceContext) => string;
|
|
48
|
+
readonly 'turn-off': (c: SentenceContext) => string;
|
|
49
|
+
readonly 'assert-on': (c: SentenceContext) => string;
|
|
50
|
+
readonly 'assert-off': (c: SentenceContext) => string;
|
|
51
|
+
readonly pick: (c: SentenceContext) => string;
|
|
52
|
+
readonly 'assert-row-count': (c: SentenceContext) => string;
|
|
53
|
+
readonly 'assert-row-contains': (c: SentenceContext) => string;
|
|
54
|
+
readonly close: (c: SentenceContext) => string;
|
|
55
|
+
readonly 'assert-open': (c: SentenceContext) => string;
|
|
56
|
+
readonly 'assert-closed': (c: SentenceContext) => string;
|
|
57
|
+
readonly 'open-tab': (c: SentenceContext) => string;
|
|
58
|
+
readonly 'assert-active-tab': (c: SentenceContext) => string;
|
|
59
|
+
readonly 'assert-alt': (c: SentenceContext) => string;
|
|
60
|
+
readonly 'assert-loaded': (c: SentenceContext) => string;
|
|
61
|
+
readonly 'pick-date': (c: SentenceContext) => string;
|
|
62
|
+
readonly 'assert-count': (c: SentenceContext) => string;
|
|
63
|
+
readonly 'assert-tooltip': (c: SentenceContext) => string;
|
|
64
|
+
};
|
|
65
|
+
type StepAction = keyof typeof SENTENCES;
|
|
66
|
+
interface StepOptions {
|
|
67
|
+
/** Action payload (typed text, chosen option) */
|
|
68
|
+
detail?: string;
|
|
69
|
+
/** Assertions only: expected value */
|
|
70
|
+
expected?: string;
|
|
71
|
+
/** On assertion failure: how to read the value actually found */
|
|
72
|
+
readActual?: () => Promise<string>;
|
|
73
|
+
/** Sentence override for business-level narration ("Confirm the export") */
|
|
74
|
+
as?: string;
|
|
75
|
+
}
|
|
76
|
+
interface ControlOptions {
|
|
77
|
+
/** Scope the control inside another one (e.g. a button within a dialog). */
|
|
78
|
+
within?: Control;
|
|
79
|
+
/**
|
|
80
|
+
* Deterministic healing alternatives, tried in order when the primary
|
|
81
|
+
* locator stops resolving. After these, the implicit `role + name`
|
|
82
|
+
* fallback derived from the control type is tried. See RAZO_HEALING.
|
|
83
|
+
*/
|
|
84
|
+
fallbacks?: LocatorSpec[];
|
|
85
|
+
}
|
|
86
|
+
type AriaRole = Parameters<Page['getByRole']>[0];
|
|
87
|
+
/**
|
|
88
|
+
* How to find a control. A plain string means data-testid (the recommended,
|
|
89
|
+
* stable path — see the auto-testid Vite plugin); the object forms map 1:1
|
|
90
|
+
* to Playwright's user-facing locators, so razo works on apps that were
|
|
91
|
+
* never instrumented. `{ locator }` is the full escape hatch.
|
|
92
|
+
*/
|
|
93
|
+
type LocatorSpec = string | {
|
|
94
|
+
testId: string;
|
|
95
|
+
} | {
|
|
96
|
+
role: AriaRole;
|
|
97
|
+
name?: string;
|
|
98
|
+
exact?: boolean;
|
|
99
|
+
} | {
|
|
100
|
+
label: string;
|
|
101
|
+
exact?: boolean;
|
|
102
|
+
} | {
|
|
103
|
+
placeholder: string;
|
|
104
|
+
} | {
|
|
105
|
+
text: string;
|
|
106
|
+
exact?: boolean;
|
|
107
|
+
} | {
|
|
108
|
+
altText: string;
|
|
109
|
+
} | {
|
|
110
|
+
title: string;
|
|
111
|
+
} | {
|
|
112
|
+
css: string;
|
|
113
|
+
} | {
|
|
114
|
+
locator: Locator;
|
|
115
|
+
};
|
|
116
|
+
declare abstract class Control {
|
|
117
|
+
readonly page: Page;
|
|
118
|
+
readonly name: string;
|
|
119
|
+
protected abstract readonly controlType: string;
|
|
120
|
+
/** @deprecated Only set when the control was located by testid; use `selector`. */
|
|
121
|
+
readonly testId: string;
|
|
122
|
+
private _locator;
|
|
123
|
+
private _selector;
|
|
124
|
+
private readonly parent?;
|
|
125
|
+
private readonly fallbacks;
|
|
126
|
+
/**
|
|
127
|
+
* Root that fallbacks resolve against — read lazily so a child control
|
|
128
|
+
* follows its `within` parent even after the PARENT healed.
|
|
129
|
+
*/
|
|
130
|
+
private get healRoot();
|
|
131
|
+
private get withinPrefix();
|
|
132
|
+
/** The Playwright locator currently backing this control. */
|
|
133
|
+
get locator(): Locator;
|
|
134
|
+
/** Readable selector, chained through `within` parents; travels in every StepEvent. */
|
|
135
|
+
get selector(): string;
|
|
136
|
+
constructor(page: Page, locate: LocatorSpec, name: string, options?: ControlOptions);
|
|
137
|
+
/**
|
|
138
|
+
* Core of the framework: runs `fn` inside a test.step titled with the
|
|
139
|
+
* grammar sentence, and emits the matching structured StepEvent —
|
|
140
|
+
* also (especially) when it fails.
|
|
141
|
+
*/
|
|
142
|
+
protected step<T>(action: StepAction, options: StepOptions, fn: () => Promise<T>): Promise<T>;
|
|
143
|
+
/** True when the primary locator currently matches nothing (safe: never throws). */
|
|
144
|
+
private primaryGone;
|
|
145
|
+
/** First fallback (explicit, then implicit role+name) resolving to exactly one element. */
|
|
146
|
+
private findHealingSpec;
|
|
147
|
+
/**
|
|
148
|
+
* Same-role elements on the page, as evidence for the analyzer to propose
|
|
149
|
+
* a replacement locator. Best-effort: capped, time-boxed, never throws.
|
|
150
|
+
*/
|
|
151
|
+
private collectDomCandidates;
|
|
152
|
+
expectVisible(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
153
|
+
expectEnabled(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
154
|
+
expectDisabled(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
155
|
+
expectText(expected: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
156
|
+
/** The control as it appears in the narration: `button "Export"`. */
|
|
157
|
+
describe(): string;
|
|
158
|
+
hover(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
159
|
+
doubleClick(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
160
|
+
rightClick(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
161
|
+
press(key: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
162
|
+
focus(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
163
|
+
scrollTo(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
164
|
+
dragTo(target: Control, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
165
|
+
expectHidden(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
166
|
+
expectFocused(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
167
|
+
expectContainsText(expected: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
168
|
+
expectAttribute(attribute: string, expected: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
169
|
+
/** For repeated testids (list items): how many elements the control matches. */
|
|
170
|
+
expectCount(expected: number, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
declare class Button extends Control {
|
|
174
|
+
protected readonly controlType = "button";
|
|
175
|
+
click(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
declare class Input extends Control {
|
|
179
|
+
protected readonly controlType: string;
|
|
180
|
+
/** For a field, "text" means its value, not its DOM content. */
|
|
181
|
+
expectText(expected: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
182
|
+
fill(value: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
183
|
+
clear(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
184
|
+
expectEmpty(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Radio group: the testId points at the group container. */
|
|
188
|
+
declare class RadioButton extends Control {
|
|
189
|
+
protected readonly controlType = "radio group";
|
|
190
|
+
select(option: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
191
|
+
expectSelected(option: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
declare class Checkbox extends Control {
|
|
195
|
+
protected readonly controlType = "checkbox";
|
|
196
|
+
private readActualState;
|
|
197
|
+
expectChecked(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
198
|
+
expectUnchecked(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
199
|
+
check(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
200
|
+
uncheck(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
declare class Select extends Control {
|
|
204
|
+
protected readonly controlType = "select";
|
|
205
|
+
/** Chooses an option by its visible label. */
|
|
206
|
+
choose(option: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
207
|
+
/** Chooses several options by label (for <select multiple>). */
|
|
208
|
+
chooseMany(optionLabels: string[], options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
declare class Link extends Control {
|
|
212
|
+
protected readonly controlType = "link";
|
|
213
|
+
open(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
214
|
+
expectHref(expected: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Read-only element (status messages, headings). It has no actions:
|
|
219
|
+
* it exists so outcome verifications are narrated too.
|
|
220
|
+
*/
|
|
221
|
+
declare class Label extends Control {
|
|
222
|
+
protected readonly controlType = "label";
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
declare class FileInput extends Control {
|
|
226
|
+
protected readonly controlType = "file input";
|
|
227
|
+
/** Attaches one or more files by path. The narration shows the file names. */
|
|
228
|
+
attach(files: string | string[], options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
229
|
+
clear(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
230
|
+
/** Asserts the name of the file currently selected. */
|
|
231
|
+
expectFile(expectedName: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
declare class Slider extends Control {
|
|
235
|
+
protected readonly controlType = "slider";
|
|
236
|
+
/**
|
|
237
|
+
* Sets the slider value. Range inputs cannot be filled, so the value is
|
|
238
|
+
* set in the DOM and the input/change events the app listens to are fired.
|
|
239
|
+
*/
|
|
240
|
+
setValue(value: number | string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
241
|
+
expectValue(expected: number | string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** Same behavior as Input; only the narration names it differently. */
|
|
245
|
+
declare class TextArea extends Input {
|
|
246
|
+
protected readonly controlType = "text area";
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** ARIA switch (role="switch" with aria-checked). Actions are idempotent. */
|
|
250
|
+
declare class Switch extends Control {
|
|
251
|
+
protected readonly controlType = "switch";
|
|
252
|
+
private readState;
|
|
253
|
+
turnOn(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
254
|
+
turnOff(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
255
|
+
expectOn(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
256
|
+
expectOff(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* ARIA combobox: the testId points at the text input; options are looked up
|
|
261
|
+
* by role anywhere on the page (comboboxes often render their listbox in a
|
|
262
|
+
* portal outside the input's subtree).
|
|
263
|
+
*/
|
|
264
|
+
declare class Combobox extends Control {
|
|
265
|
+
protected readonly controlType = "combobox";
|
|
266
|
+
search(text: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
267
|
+
pick(option: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
268
|
+
expectSelected(expected: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** Read-only table assertions over tbody rows. */
|
|
272
|
+
declare class Table extends Control {
|
|
273
|
+
protected readonly controlType = "table";
|
|
274
|
+
private rows;
|
|
275
|
+
expectRowCount(expected: number, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
276
|
+
expectRowContains(expected: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** Native <dialog> or role="dialog". close() sends Escape. */
|
|
280
|
+
declare class Dialog extends Control {
|
|
281
|
+
protected readonly controlType = "dialog";
|
|
282
|
+
private readState;
|
|
283
|
+
close(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
284
|
+
expectOpen(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
285
|
+
expectClosed(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** ARIA tablist: the testId points at the tablist container. */
|
|
289
|
+
declare class Tabs extends Control {
|
|
290
|
+
protected readonly controlType = "tabs";
|
|
291
|
+
open(tab: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
292
|
+
expectActive(expected: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
declare class Image extends Control {
|
|
296
|
+
protected readonly controlType = "image";
|
|
297
|
+
expectAlt(expected: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
298
|
+
expectLoaded(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/** Native input[type="date"]; dates travel in ISO format (YYYY-MM-DD). */
|
|
302
|
+
declare class DatePicker extends Control {
|
|
303
|
+
protected readonly controlType = "date picker";
|
|
304
|
+
pick(isoDate: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
305
|
+
expectDate(expected: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Dropdown menu: the testId points at the trigger button; menu items are
|
|
310
|
+
* looked up by role anywhere on the page (menus often render in portals).
|
|
311
|
+
*/
|
|
312
|
+
declare class Menu extends Control {
|
|
313
|
+
protected readonly controlType = "menu";
|
|
314
|
+
choose(item: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Tooltip: the testId points at the TRIGGER element. The tooltip content is
|
|
319
|
+
* resolved through the trigger's aria-describedby (the accessible pattern),
|
|
320
|
+
* so it works wherever the tooltip node is rendered.
|
|
321
|
+
*/
|
|
322
|
+
declare class Tooltip extends Control {
|
|
323
|
+
protected readonly controlType = "tooltip";
|
|
324
|
+
private tooltipText;
|
|
325
|
+
/** Hovers the trigger and asserts the tooltip content. */
|
|
326
|
+
expectContent(expected: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/** contenteditable region. Inherits expectText/expectContainsText from the base. */
|
|
330
|
+
declare class Editor extends Control {
|
|
331
|
+
protected readonly controlType = "editor";
|
|
332
|
+
write(text: string, options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
333
|
+
clear(options?: Pick<StepOptions, 'as'>): Promise<void>;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export { Button, Checkbox, Combobox, Control, type ControlOptions, DatePicker, Dialog, Editor, FileInput, Image, Input, Label, Link, type LocatorSpec, Menu, RadioButton, Select, Slider, type StepAction, type StepOptions, Switch, Table, Tabs, TextArea, Tooltip };
|