@bloom-perf/yaml-pptr 3.0.0 → 3.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/README.md +44 -0
- package/dist/index.js +2 -2
- package/dist/schema.json +900 -0
- package/dist/yaml/json-schema.d.ts +6 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -177,6 +177,28 @@ try {
|
|
|
177
177
|
}
|
|
178
178
|
```
|
|
179
179
|
|
|
180
|
+
## Editor Support
|
|
181
|
+
|
|
182
|
+
The package ships a JSON Schema of the YAML configuration (`dist/schema.json`), generated from the very schema used to validate it at runtime. With the [YAML extension for VS Code](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) (or any editor using `yaml-language-server`), you get completion, documentation on hover, and errors (unknown key, wrong type...) while typing.
|
|
183
|
+
|
|
184
|
+
Add this first line to a scenario file:
|
|
185
|
+
|
|
186
|
+
```yaml
|
|
187
|
+
# yaml-language-server: $schema=https://unpkg.com/@bloom-perf/yaml-pptr@3/dist/schema.json
|
|
188
|
+
scenarios:
|
|
189
|
+
- name: Login
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
With the package installed, a local path works too (relative to the YAML file), e.g. `$schema=../node_modules/@bloom-perf/yaml-pptr/dist/schema.json`. To apply it to several files, map them in `.vscode/settings.json`:
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"yaml.schemas": {
|
|
197
|
+
"https://unpkg.com/@bloom-perf/yaml-pptr@3/dist/schema.json": ["scenarios/*.yaml"]
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
180
202
|
## YAML Reference
|
|
181
203
|
|
|
182
204
|
### Scenario Configuration
|
|
@@ -195,6 +217,28 @@ try {
|
|
|
195
217
|
|
|
196
218
|
All the scenarios of a file start at the same time, whatever their browser: each one is a population of users with its own `workers`, `iterations` and start strategy. Unknown keys are rejected (see [Error handling](#error-handling)).
|
|
197
219
|
|
|
220
|
+
### Selectors
|
|
221
|
+
|
|
222
|
+
Every selector (`click`, `input`, `CLICK`, `TYPE`, `WAIT_FOR_SELECTOR`) accepts a CSS selector or any [Puppeteer selector](https://pptr.dev/guides/page-interactions), so XPath, text and ARIA queries need no special syntax:
|
|
223
|
+
|
|
224
|
+
| Kind | Example |
|
|
225
|
+
| ---- | ------- |
|
|
226
|
+
| CSS | `#login-button`, `form .submit` |
|
|
227
|
+
| XPath | `::-p-xpath(//button[@type='submit'])` or `xpath///button[@type='submit']` |
|
|
228
|
+
| Text | `::-p-text(Sign in)` |
|
|
229
|
+
| ARIA | `::-p-aria(Sign in)`, `::-p-aria([name="Sign in"][role="button"])` |
|
|
230
|
+
| Shadow DOM | `my-app >>> button` (any depth), `my-app >>>> button` (direct shadow root) |
|
|
231
|
+
|
|
232
|
+
```yaml
|
|
233
|
+
steps:
|
|
234
|
+
- input:
|
|
235
|
+
selector: "::-p-xpath(//input[@name='email'])"
|
|
236
|
+
text: "${APP_USER}"
|
|
237
|
+
- click: "::-p-text(Sign in)"
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
`${VAR}` placeholders are resolved in selectors too.
|
|
241
|
+
|
|
198
242
|
### Steps (Simplified Syntax)
|
|
199
243
|
|
|
200
244
|
#### click
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import*as
|
|
2
|
-
${
|
|
1
|
+
import*as F from"js-yaml";import*as _ from"zod";import*as t from"zod";var y=t.number().int().nonnegative(),v=t.number().int().positive(),$=t.string().describe("CSS selector, or Puppeteer selector: ::-p-xpath(...), ::-p-text(...), ::-p-aria(...), xpath/..., >>> (shadow DOM). ${VAR} placeholders are resolved."),W=t.string().describe('URL. "$VAR" as the whole value, or ${VAR} placeholders anywhere.'),L=t.enum(["load","domcontentloaded","networkidle0","networkidle2"]),M=t.enum(["left","right","middle"]),D=t.enum(["chrome","firefox"]),Z=t.strictObject({timeout:y.optional().describe("Navigation timeout in milliseconds."),waitUntil:t.union([L,L.array()]).optional().describe("When to consider the navigation finished."),referer:t.string().optional().describe("Referer header. ${VAR} placeholders are resolved.")}).optional(),H=t.strictObject({button:M.optional(),clickCount:v.optional().describe("2 for a double-click."),delay:y.optional().describe("Milliseconds between mousedown and mouseup.")}).optional(),K=t.strictObject({delay:y.optional().describe("Milliseconds between keystrokes.")}).optional(),q=t.strictObject({visible:t.boolean().optional(),hidden:t.boolean().optional(),timeout:y.optional().describe("Timeout in milliseconds.")}).optional(),Q=t.strictObject({type:t.enum(["png","jpeg"]).optional(),quality:t.number().int().min(0).max(100).optional().describe("JPEG quality (0-100)."),fullPage:t.boolean().optional(),clip:t.strictObject({x:t.number(),y:t.number(),width:t.number().positive(),height:t.number().positive()}).optional(),omitBackground:t.boolean().optional(),encoding:t.enum(["base64","binary"]).optional()}).optional(),J=t.strictObject({type:t.literal("GOTO"),url:W,options:Z}).describe("Navigate to a URL, with navigation options."),X=t.strictObject({type:t.literal("CLICK"),selector:$,options:H}).describe("Click on an element."),Y=t.strictObject({type:t.literal("TYPE"),selector:$,text:t.string().describe("Text to type. ${VAR} placeholders are resolved (keep credentials in environment variables). Never logged."),options:K}).describe("Type text into an element."),ee=t.strictObject({type:t.literal("WAIT_FOR_SELECTOR"),selector:$,options:q}).describe("Wait for an element to appear (or to be visible / hidden)."),te=t.strictObject({type:t.literal("WAIT_FOR_TIMEOUT"),timeout:y.describe("Milliseconds.")}).describe("Wait for a duration in milliseconds."),oe=t.strictObject({type:t.literal("WAIT"),milliseconds:y}).describe("Wait for a duration in milliseconds."),re=t.strictObject({type:t.literal("PAUSE")}).describe("Wait for Enter in an interactive terminal (debugging). Ignored with a warning when there is none."),ie=t.strictObject({type:t.literal("SCREENSHOT"),path:t.string().describe('File path. "$VAR" as the whole value, or ${VAR} placeholders anywhere.'),options:Q}).describe("Take a screenshot."),ne=t.strictObject({type:t.literal("EVALUATE"),script:t.string().describe("JavaScript evaluated in the page. Never interpolated.")}).describe("Evaluate JavaScript in the page."),se=t.strictObject({type:t.literal("SET_VIEWPORT"),width:v,height:v}).describe("Set the page viewport size."),ae=t.strictObject({type:t.literal("CLOSE")}).describe("Close the page."),P=t.discriminatedUnion("type",[J,X,Y,ee,te,oe,re,ie,ne,se,ae]),ce=t.strictObject({navigate:W}).describe('Navigate to a URL ("$VAR[workerIndex]" gives one URL per worker).'),pe=t.literal("waitForever").describe("Keep the page open forever."),le=t.strictObject({wait:t.number().nonnegative().describe("Seconds.")}).describe("Wait for a duration in seconds."),ue=t.strictObject({click:$}).describe("Click on an element."),de=t.strictObject({input:t.strictObject({selector:$,text:t.string().describe("Text to type. ${VAR} placeholders are resolved (keep credentials in environment variables). Never logged.")})}).describe("Type text into an element."),ge=t.union([ce,pe,le,ue,de,P]),he=t.strictObject({name:t.string().optional().describe('Scenario name (default: "Scenario <n>").'),browser:D.optional().describe("Browser to use (default: chrome)."),run:t.enum(["PARALLEL","SEQUENTIAL"]).optional().describe("Worker start strategy (default: PARALLEL). PARALLEL: all workers start after initialDelaySeconds. SEQUENTIAL: worker n starts after n \xD7 initialDelaySeconds."),initialDelaySeconds:t.number().nonnegative().optional().describe("Start delay, applied once per worker before its first iteration (see run)."),workers:v.optional().describe("Number of parallel workers (default: 1)."),iterations:v.optional().describe("Repetitions per worker (default: 1)."),location:W.optional().describe('Starting URL. "$VAR", ${VAR} placeholders, or "$VAR[workerIndex]" for one URL per worker.'),steps:t.array(ge).optional().describe("Shorthand steps; full actions are accepted too, to mix both syntaxes in order."),actions:t.array(P).optional().describe("Full actions, run after steps.")}).describe("A population of users: its workers run the steps and actions for the given number of iterations."),B=t.strictObject({scenarios:t.array(he).describe("Scenarios, all started at the same time.")});var V=r=>r instanceof Error?r.message:String(r),b=class extends Error{constructor(e,o){super(e,o),this.name="ConfigurationError"}},T=class extends Error{scenarioName;workerIndex;iteration;constructor(e,o,i,n){super(`Scenario "${e}" (worker ${o}, iteration ${i}) failed: ${V(n)}`,{cause:n}),this.name="WorkerError",this.scenarioName=e,this.workerIndex=o,this.iteration=i}},E=class extends Error{browser;constructor(e,o){super(`Failed to launch browser "${e}": ${V(o)}`,{cause:o}),this.name="BrowserLaunchError",this.browser=e}};var I=r=>{let e;try{e=F.load(r)}catch(i){throw new b(`Invalid YAML syntax: ${i instanceof Error?i.message:String(i)}`,{cause:i})}let o=B.safeParse(e);if(!o.success)throw new b(`Invalid scenario configuration:
|
|
2
|
+
${_.prettifyError(o.error)}`,{cause:o.error});return o.data};var f={debug(r){console.log(r)},info(r){console.log(r)},warn(r){console.log(r)},error(r){console.error(r)}};var we=/^[A-Za-z_][A-Za-z0-9_]*$/,be=/^\$([A-Za-z_][A-Za-z0-9_]*)$/,Se=/^\$([A-Za-z_][A-Za-z0-9_]*)\[workerIndex\]$/,fe=/\$\$\{|\$\{([^}]*)\}/g,U='per-worker values ("$VAR[workerIndex]") are only supported as the whole value of location and navigate',O=class{envVarResolve;logger;constructor(e,o=f){this.envVarResolve=e,this.logger=o}resolve(e){return{scenarios:e.scenarios.map((o,i)=>this.resolveScenario(o,i+1))}}resolveScenario(e,o){let i={name:e.name||`Scenario ${o}`,workers:e.workers||1};this.logger.debug(`Resolving scenario "${i.name}" (${e.steps?.length??0} step(s), ${e.actions?.length??0} action(s))`);let n=[];try{e.location&&n.push(this.createNavigateAction(e.location,i));for(let s of e.steps??[])n.push(this.resolveStep(s,i));for(let s of e.actions??[])n.push(this.resolveAction(s))}catch(s){throw new b(`Scenario "${i.name}": ${s instanceof Error?s.message:String(s)}`,{cause:s})}let a=e.run==="SEQUENTIAL"?{delaySecondsBetweenWorkerInits:e.initialDelaySeconds||0}:{initialDelaySeconds:e.initialDelaySeconds||0};return{name:i.name,browser:e.browser||"chrome",run:a,workers:i.workers,iterations:e.iterations||1,actions:n}}resolveStep(e,o){return e==="waitForever"?{actionType:"WaitForever"}:"type"in e?this.resolveAction(e):"wait"in e?{actionType:"Wait",milliseconds:e.wait*1e3}:"navigate"in e?this.createNavigateAction(e.navigate,o):"click"in e?{actionType:"CLICK",selector:this.interpolate(e.click)}:{actionType:"TYPE",selector:this.interpolate(e.input.selector),text:this.interpolate(e.input.text)}}resolveAction(e){switch(this.logger.debug(`Resolving action: ${e.type}`),e.type){case"GOTO":return{actionType:"GOTO",url:this.resolveWholeValueOrInterpolate(e.url),options:e.options&&{...e.options,referer:e.options.referer&&this.interpolate(e.options.referer)}};case"WAIT":return{actionType:"Wait",milliseconds:e.milliseconds};case"CLICK":return{actionType:"CLICK",selector:this.interpolate(e.selector),options:e.options};case"TYPE":return{actionType:"TYPE",selector:this.interpolate(e.selector),text:this.interpolate(e.text),options:e.options};case"WAIT_FOR_SELECTOR":return{actionType:"WAIT_FOR_SELECTOR",selector:this.interpolate(e.selector),options:e.options};case"WAIT_FOR_TIMEOUT":return{actionType:"WAIT_FOR_TIMEOUT",timeout:e.timeout};case"PAUSE":return{actionType:"PAUSE"};case"SCREENSHOT":return{actionType:"SCREENSHOT",path:this.resolveWholeValueOrInterpolate(e.path),options:e.options};case"EVALUATE":return{actionType:"EVALUATE",script:e.script};case"SET_VIEWPORT":return{actionType:"SET_VIEWPORT",width:e.width,height:e.height};case"CLOSE":return{actionType:"CLOSE"};default:return e}}createNavigateAction(e,o){let i=Se.exec(e);if(i){let n=i[1],a=this.env(n).split(",").map(s=>s.trim());if(a.some(s=>s===""))throw new Error(`environment variable "${n}" (used as "${e}") contains an empty value`);if(a.length<o.workers)throw new Error(`environment variable "${n}" (used as "${e}") provides ${a.length} value(s) for ${o.workers} worker(s)`);return{actionType:"Navigate",location:{workerIndex:a}}}return{actionType:"Navigate",location:{url:this.resolveWholeValueOrInterpolate(e)}}}resolveWholeValueOrInterpolate(e){let o=be.exec(e);if(o)return this.env(o[1]);if(/^\$[A-Za-z_]/.test(e))throw new Error(`unsupported environment variable reference "${e}": use "$VAR" for the whole value or "\${VAR}" inside a value`+(e.endsWith("[workerIndex]")?`; ${U}`:""));return this.interpolate(e)}interpolate(e){return e.replace(fe,(o,i)=>{if(o==="$${")return"${";if(i===void 0||!we.test(i))throw new Error(`invalid placeholder "${o}": expected \${VAR_NAME}`+(i?.endsWith("[workerIndex]")?`; ${U}`:""));return this.env(i)})}env(e){return this.logger.debug(`Resolving environment variable "${e}"`),this.envVarResolve(e)}};import{setTimeout as x}from"node:timers/promises";function Ae(r,e){let o=e||"png";return r.endsWith(".png")||r.endsWith(".jpeg")||r.endsWith(".jpg")||r.endsWith(".webp")?r:`${r}.${o}`}var ye=(r,e)=>"delaySecondsBetweenWorkerInits"in r?r.delaySecondsBetweenWorkerInits*e:r.initialDelaySeconds,j=async(r,e,o=f,i)=>{let n=[],a=async s=>{let p=ye(e.run,s),m="delaySecondsBetweenWorkerInits"in e.run?"SEQUENTIAL":"PARALLEL";o.info(`Scenario "${e.name}" (worker ${s}) started (${m}, starting in ${p}s).`),await x(p*1e3);for(let u=0;u<e.iterations;u++)try{await ve(r,e,s,u,o,i)}catch(S){let g=new T(e.name,s,u,S);o.error(g.message),n.push(g)}};if(await Promise.all(Array.from({length:e.workers},(s,p)=>a(p))),n.length>0){n.sort((p,m)=>p.workerIndex-m.workerIndex||p.iteration-m.iteration);let s=e.workers*e.iterations;throw new AggregateError(n,`Scenario "${e.name}": ${n.length}/${s} iteration(s) failed`)}},ve=async(r,e,o,i,n,a)=>{let s;try{s=await r.newPage(),a&&await a(s,{scenarioName:e.name,workerIndex:o,iteration:i}),await $e(e.name,e.actions,s,o,n)}finally{s&&!s.isClosed()&&await s.close().catch(p=>n.warn(`Scenario "${e.name}" (worker ${o}, iteration ${i}) > failed to close page: ${p}`))}},$e=async(r,e,o,i,n=f)=>{for(let a of e){let{actionType:s}=a;switch(s){case"Navigate":let p=a;"url"in p.location?(n.info(`Scenario "${r}" (worker ${i}) > Navigating to location "${p.location.url}"`),await o.goto(p.location.url)):(n.info(`Scenario "${r}" (worker ${i}) > Navigating to indexed location "${p.location.workerIndex[i]}"`),await o.goto(p.location.workerIndex[i]));break;case"Wait":let m=a;n.info(`Scenario "${r}" (worker ${i}) > Waiting ${m.milliseconds} milliseconds...`),await x(m.milliseconds);break;case"WaitForever":for(n.info(`Scenario "${r}" (worker ${i}) > Waiting forever...`);;)await x(3600*1e3);break;case"GOTO":let u=a;n.info(`Scenario "${r}" (worker ${i}) > GOTO "${u.url}"`);let S={timeout:u.options?.timeout,waitUntil:u.options?.waitUntil,referer:u.options?.referer};await o.goto(u.url,S);break;case"CLICK":let g=a;n.info(`Scenario "${r}" (worker ${i}) > CLICK on "${g.selector}"`);let C={button:g.options?.button,clickCount:g.options?.clickCount,delay:g.options?.delay};await o.click(g.selector,C);break;case"TYPE":let w=a;n.info(`Scenario "${r}" (worker ${i}) > TYPE into "${w.selector}"`),await o.type(w.selector,w.text,w.options);break;case"WAIT_FOR_SELECTOR":let c=a;n.info(`Scenario "${r}" (worker ${i}) > WAIT_FOR_SELECTOR "${c.selector}"`),await o.waitForSelector(c.selector,c.options);break;case"WAIT_FOR_TIMEOUT":let d=a;n.info(`Scenario "${r}" (worker ${i}) > WAIT_FOR_TIMEOUT ${d.timeout} milliseconds`),await x(d.timeout);break;case"PAUSE":if(!process.stdin.isTTY){n.warn(`Scenario "${r}" (worker ${i}) > PAUSE ignored: no interactive terminal`);break}n.info(`Scenario "${r}" (worker ${i}) > PAUSE, press Enter to continue...`),await new Promise(A=>{process.stdin.resume(),process.stdin.once("data",()=>{process.stdin.pause(),A()})});break;case"SCREENSHOT":let l=a;n.info(`Scenario "${r}" (worker ${i}) > SCREENSHOT "${l.path}"`);let R={path:Ae(l.path,l.options?.type),type:l.options?.type,quality:l.options?.quality,fullPage:l.options?.fullPage,clip:l.options?.clip,omitBackground:l.options?.omitBackground,encoding:l.options?.encoding};await o.screenshot(R);break;case"EVALUATE":let k=a;n.info(`Scenario "${r}" (worker ${i}) > EVALUATE script`),await o.evaluate(k.script);break;case"SET_VIEWPORT":let h=a;n.info(`Scenario "${r}" (worker ${i}) > SET_VIEWPORT width=${h.width}, height=${h.height}`),await o.setViewport({width:h.width,height:h.height});break;case"CLOSE":n.info(`Scenario "${r}" (worker ${i}) > CLOSE page`),await o.close();break;default:throw new Error(`Unhandled action type "${s}" while evaluating scenario "${r}" on worker ${i}`)}}};import*as N from"puppeteer";var Te=(r,e)=>{if(r==="firefox")return[];let o=["--no-sandbox","--disable-setuid-sandbox","--disable-dev-shm-usage","--disable-accelerated-2d-canvas","--disable-gpu","--ignore-certificate-errors"];return e||o.push("--start-maximized"),o},Ee=(r,e,o={})=>({browser:r,headless:e,acceptInsecureCerts:!0,...o,args:[...Te(r,e),...o.args??[]]}),G=(r,e,o)=>N.launch(Ee(r,e,o));var bt=async(r,e={})=>{let{browsers:o={},logger:i=f,onPage:n,headless:a=!0,launchOptions:s={}}=e,p=I(r),u=new O(c=>{let d=process.env[c];if(d)return d;throw new Error(`environment variable "${c}" is not set (or empty)`)},i).resolve(p),S=new Map;for(let c of u.scenarios){let d=S.get(c.browser)??[];d.push(c),S.set(c.browser,d)}let g=async(c,d)=>{let l=o[c],R=!l;if(!l)try{i.info(`Launching ${c} (headless: ${a})`),l=await G(c,a,s[c])}catch(h){let A=new E(c,h);return i.error(A.message),[A]}let k=l;try{return(await Promise.all(d.map(async A=>{try{return await j(k,A,i,n),[]}catch(z){return z instanceof AggregateError?z.errors:[z]}}))).flat()}finally{R&&await k.close().catch(h=>i.warn(`Failed to close ${c}: ${h}`))}},w=(await Promise.all([...S].map(([c,d])=>g(c,d)))).flat();if(w.length>0)throw new AggregateError(w,`${w.length} error(s) occurred while running scenarios`)};export{E as BrowserLaunchError,b as ConfigurationError,T as WorkerError,bt as readYamlAndInterpret};
|
package/dist/schema.json
ADDED
|
@@ -0,0 +1,900 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "yaml-pptr scenarios",
|
|
4
|
+
"description": "Scenarios run by @bloom-perf/yaml-pptr — https://github.com/Bloom-Perf/yaml-pptr",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"scenarios": {
|
|
8
|
+
"type": "array",
|
|
9
|
+
"items": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"name": {
|
|
13
|
+
"description": "Scenario name (default: \"Scenario <n>\").",
|
|
14
|
+
"type": "string"
|
|
15
|
+
},
|
|
16
|
+
"browser": {
|
|
17
|
+
"description": "Browser to use (default: chrome).",
|
|
18
|
+
"type": "string",
|
|
19
|
+
"enum": [
|
|
20
|
+
"chrome",
|
|
21
|
+
"firefox"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
"run": {
|
|
25
|
+
"description": "Worker start strategy (default: PARALLEL). PARALLEL: all workers start after initialDelaySeconds. SEQUENTIAL: worker n starts after n × initialDelaySeconds.",
|
|
26
|
+
"type": "string",
|
|
27
|
+
"enum": [
|
|
28
|
+
"PARALLEL",
|
|
29
|
+
"SEQUENTIAL"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"initialDelaySeconds": {
|
|
33
|
+
"description": "Start delay, applied once per worker before its first iteration (see run).",
|
|
34
|
+
"type": "number",
|
|
35
|
+
"minimum": 0
|
|
36
|
+
},
|
|
37
|
+
"workers": {
|
|
38
|
+
"description": "Number of parallel workers (default: 1).",
|
|
39
|
+
"type": "integer",
|
|
40
|
+
"exclusiveMinimum": 0,
|
|
41
|
+
"maximum": 9007199254740991
|
|
42
|
+
},
|
|
43
|
+
"iterations": {
|
|
44
|
+
"description": "Repetitions per worker (default: 1).",
|
|
45
|
+
"type": "integer",
|
|
46
|
+
"exclusiveMinimum": 0,
|
|
47
|
+
"maximum": 9007199254740991
|
|
48
|
+
},
|
|
49
|
+
"location": {
|
|
50
|
+
"description": "Starting URL. \"$VAR\", ${VAR} placeholders, or \"$VAR[workerIndex]\" for one URL per worker.",
|
|
51
|
+
"type": "string"
|
|
52
|
+
},
|
|
53
|
+
"steps": {
|
|
54
|
+
"description": "Shorthand steps; full actions are accepted too, to mix both syntaxes in order.",
|
|
55
|
+
"type": "array",
|
|
56
|
+
"items": {
|
|
57
|
+
"anyOf": [
|
|
58
|
+
{
|
|
59
|
+
"type": "object",
|
|
60
|
+
"properties": {
|
|
61
|
+
"navigate": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"description": "URL. \"$VAR\" as the whole value, or ${VAR} placeholders anywhere."
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"required": [
|
|
67
|
+
"navigate"
|
|
68
|
+
],
|
|
69
|
+
"additionalProperties": false,
|
|
70
|
+
"description": "Navigate to a URL (\"$VAR[workerIndex]\" gives one URL per worker)."
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"type": "string",
|
|
74
|
+
"const": "waitForever",
|
|
75
|
+
"description": "Keep the page open forever."
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"type": "object",
|
|
79
|
+
"properties": {
|
|
80
|
+
"wait": {
|
|
81
|
+
"type": "number",
|
|
82
|
+
"minimum": 0,
|
|
83
|
+
"description": "Seconds."
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"required": [
|
|
87
|
+
"wait"
|
|
88
|
+
],
|
|
89
|
+
"additionalProperties": false,
|
|
90
|
+
"description": "Wait for a duration in seconds."
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"type": "object",
|
|
94
|
+
"properties": {
|
|
95
|
+
"click": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"description": "CSS selector, or Puppeteer selector: ::-p-xpath(...), ::-p-text(...), ::-p-aria(...), xpath/..., >>> (shadow DOM). ${VAR} placeholders are resolved."
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"required": [
|
|
101
|
+
"click"
|
|
102
|
+
],
|
|
103
|
+
"additionalProperties": false,
|
|
104
|
+
"description": "Click on an element."
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"type": "object",
|
|
108
|
+
"properties": {
|
|
109
|
+
"input": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"properties": {
|
|
112
|
+
"selector": {
|
|
113
|
+
"type": "string",
|
|
114
|
+
"description": "CSS selector, or Puppeteer selector: ::-p-xpath(...), ::-p-text(...), ::-p-aria(...), xpath/..., >>> (shadow DOM). ${VAR} placeholders are resolved."
|
|
115
|
+
},
|
|
116
|
+
"text": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"description": "Text to type. ${VAR} placeholders are resolved (keep credentials in environment variables). Never logged."
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"required": [
|
|
122
|
+
"selector",
|
|
123
|
+
"text"
|
|
124
|
+
],
|
|
125
|
+
"additionalProperties": false
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
"required": [
|
|
129
|
+
"input"
|
|
130
|
+
],
|
|
131
|
+
"additionalProperties": false,
|
|
132
|
+
"description": "Type text into an element."
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"oneOf": [
|
|
136
|
+
{
|
|
137
|
+
"type": "object",
|
|
138
|
+
"properties": {
|
|
139
|
+
"type": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"const": "GOTO"
|
|
142
|
+
},
|
|
143
|
+
"url": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"description": "URL. \"$VAR\" as the whole value, or ${VAR} placeholders anywhere."
|
|
146
|
+
},
|
|
147
|
+
"options": {
|
|
148
|
+
"type": "object",
|
|
149
|
+
"properties": {
|
|
150
|
+
"timeout": {
|
|
151
|
+
"description": "Navigation timeout in milliseconds.",
|
|
152
|
+
"type": "integer",
|
|
153
|
+
"minimum": 0,
|
|
154
|
+
"maximum": 9007199254740991
|
|
155
|
+
},
|
|
156
|
+
"waitUntil": {
|
|
157
|
+
"description": "When to consider the navigation finished.",
|
|
158
|
+
"anyOf": [
|
|
159
|
+
{
|
|
160
|
+
"type": "string",
|
|
161
|
+
"enum": [
|
|
162
|
+
"load",
|
|
163
|
+
"domcontentloaded",
|
|
164
|
+
"networkidle0",
|
|
165
|
+
"networkidle2"
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"type": "array",
|
|
170
|
+
"items": {
|
|
171
|
+
"type": "string",
|
|
172
|
+
"enum": [
|
|
173
|
+
"load",
|
|
174
|
+
"domcontentloaded",
|
|
175
|
+
"networkidle0",
|
|
176
|
+
"networkidle2"
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
},
|
|
182
|
+
"referer": {
|
|
183
|
+
"description": "Referer header. ${VAR} placeholders are resolved.",
|
|
184
|
+
"type": "string"
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
"additionalProperties": false
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"required": [
|
|
191
|
+
"type",
|
|
192
|
+
"url"
|
|
193
|
+
],
|
|
194
|
+
"additionalProperties": false,
|
|
195
|
+
"description": "Navigate to a URL, with navigation options."
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"type": "object",
|
|
199
|
+
"properties": {
|
|
200
|
+
"type": {
|
|
201
|
+
"type": "string",
|
|
202
|
+
"const": "CLICK"
|
|
203
|
+
},
|
|
204
|
+
"selector": {
|
|
205
|
+
"type": "string",
|
|
206
|
+
"description": "CSS selector, or Puppeteer selector: ::-p-xpath(...), ::-p-text(...), ::-p-aria(...), xpath/..., >>> (shadow DOM). ${VAR} placeholders are resolved."
|
|
207
|
+
},
|
|
208
|
+
"options": {
|
|
209
|
+
"type": "object",
|
|
210
|
+
"properties": {
|
|
211
|
+
"button": {
|
|
212
|
+
"type": "string",
|
|
213
|
+
"enum": [
|
|
214
|
+
"left",
|
|
215
|
+
"right",
|
|
216
|
+
"middle"
|
|
217
|
+
]
|
|
218
|
+
},
|
|
219
|
+
"clickCount": {
|
|
220
|
+
"description": "2 for a double-click.",
|
|
221
|
+
"type": "integer",
|
|
222
|
+
"exclusiveMinimum": 0,
|
|
223
|
+
"maximum": 9007199254740991
|
|
224
|
+
},
|
|
225
|
+
"delay": {
|
|
226
|
+
"description": "Milliseconds between mousedown and mouseup.",
|
|
227
|
+
"type": "integer",
|
|
228
|
+
"minimum": 0,
|
|
229
|
+
"maximum": 9007199254740991
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
"additionalProperties": false
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
"required": [
|
|
236
|
+
"type",
|
|
237
|
+
"selector"
|
|
238
|
+
],
|
|
239
|
+
"additionalProperties": false,
|
|
240
|
+
"description": "Click on an element."
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"type": "object",
|
|
244
|
+
"properties": {
|
|
245
|
+
"type": {
|
|
246
|
+
"type": "string",
|
|
247
|
+
"const": "TYPE"
|
|
248
|
+
},
|
|
249
|
+
"selector": {
|
|
250
|
+
"type": "string",
|
|
251
|
+
"description": "CSS selector, or Puppeteer selector: ::-p-xpath(...), ::-p-text(...), ::-p-aria(...), xpath/..., >>> (shadow DOM). ${VAR} placeholders are resolved."
|
|
252
|
+
},
|
|
253
|
+
"text": {
|
|
254
|
+
"type": "string",
|
|
255
|
+
"description": "Text to type. ${VAR} placeholders are resolved (keep credentials in environment variables). Never logged."
|
|
256
|
+
},
|
|
257
|
+
"options": {
|
|
258
|
+
"type": "object",
|
|
259
|
+
"properties": {
|
|
260
|
+
"delay": {
|
|
261
|
+
"description": "Milliseconds between keystrokes.",
|
|
262
|
+
"type": "integer",
|
|
263
|
+
"minimum": 0,
|
|
264
|
+
"maximum": 9007199254740991
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
"additionalProperties": false
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
"required": [
|
|
271
|
+
"type",
|
|
272
|
+
"selector",
|
|
273
|
+
"text"
|
|
274
|
+
],
|
|
275
|
+
"additionalProperties": false,
|
|
276
|
+
"description": "Type text into an element."
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"type": "object",
|
|
280
|
+
"properties": {
|
|
281
|
+
"type": {
|
|
282
|
+
"type": "string",
|
|
283
|
+
"const": "WAIT_FOR_SELECTOR"
|
|
284
|
+
},
|
|
285
|
+
"selector": {
|
|
286
|
+
"type": "string",
|
|
287
|
+
"description": "CSS selector, or Puppeteer selector: ::-p-xpath(...), ::-p-text(...), ::-p-aria(...), xpath/..., >>> (shadow DOM). ${VAR} placeholders are resolved."
|
|
288
|
+
},
|
|
289
|
+
"options": {
|
|
290
|
+
"type": "object",
|
|
291
|
+
"properties": {
|
|
292
|
+
"visible": {
|
|
293
|
+
"type": "boolean"
|
|
294
|
+
},
|
|
295
|
+
"hidden": {
|
|
296
|
+
"type": "boolean"
|
|
297
|
+
},
|
|
298
|
+
"timeout": {
|
|
299
|
+
"description": "Timeout in milliseconds.",
|
|
300
|
+
"type": "integer",
|
|
301
|
+
"minimum": 0,
|
|
302
|
+
"maximum": 9007199254740991
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
"additionalProperties": false
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
"required": [
|
|
309
|
+
"type",
|
|
310
|
+
"selector"
|
|
311
|
+
],
|
|
312
|
+
"additionalProperties": false,
|
|
313
|
+
"description": "Wait for an element to appear (or to be visible / hidden)."
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
"type": "object",
|
|
317
|
+
"properties": {
|
|
318
|
+
"type": {
|
|
319
|
+
"type": "string",
|
|
320
|
+
"const": "WAIT_FOR_TIMEOUT"
|
|
321
|
+
},
|
|
322
|
+
"timeout": {
|
|
323
|
+
"type": "integer",
|
|
324
|
+
"minimum": 0,
|
|
325
|
+
"maximum": 9007199254740991,
|
|
326
|
+
"description": "Milliseconds."
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
"required": [
|
|
330
|
+
"type",
|
|
331
|
+
"timeout"
|
|
332
|
+
],
|
|
333
|
+
"additionalProperties": false,
|
|
334
|
+
"description": "Wait for a duration in milliseconds."
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
"type": "object",
|
|
338
|
+
"properties": {
|
|
339
|
+
"type": {
|
|
340
|
+
"type": "string",
|
|
341
|
+
"const": "WAIT"
|
|
342
|
+
},
|
|
343
|
+
"milliseconds": {
|
|
344
|
+
"type": "integer",
|
|
345
|
+
"minimum": 0,
|
|
346
|
+
"maximum": 9007199254740991
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
"required": [
|
|
350
|
+
"type",
|
|
351
|
+
"milliseconds"
|
|
352
|
+
],
|
|
353
|
+
"additionalProperties": false,
|
|
354
|
+
"description": "Wait for a duration in milliseconds."
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
"type": "object",
|
|
358
|
+
"properties": {
|
|
359
|
+
"type": {
|
|
360
|
+
"type": "string",
|
|
361
|
+
"const": "PAUSE"
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
"required": [
|
|
365
|
+
"type"
|
|
366
|
+
],
|
|
367
|
+
"additionalProperties": false,
|
|
368
|
+
"description": "Wait for Enter in an interactive terminal (debugging). Ignored with a warning when there is none."
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
"type": "object",
|
|
372
|
+
"properties": {
|
|
373
|
+
"type": {
|
|
374
|
+
"type": "string",
|
|
375
|
+
"const": "SCREENSHOT"
|
|
376
|
+
},
|
|
377
|
+
"path": {
|
|
378
|
+
"type": "string",
|
|
379
|
+
"description": "File path. \"$VAR\" as the whole value, or ${VAR} placeholders anywhere."
|
|
380
|
+
},
|
|
381
|
+
"options": {
|
|
382
|
+
"type": "object",
|
|
383
|
+
"properties": {
|
|
384
|
+
"type": {
|
|
385
|
+
"type": "string",
|
|
386
|
+
"enum": [
|
|
387
|
+
"png",
|
|
388
|
+
"jpeg"
|
|
389
|
+
]
|
|
390
|
+
},
|
|
391
|
+
"quality": {
|
|
392
|
+
"description": "JPEG quality (0-100).",
|
|
393
|
+
"type": "integer",
|
|
394
|
+
"minimum": 0,
|
|
395
|
+
"maximum": 100
|
|
396
|
+
},
|
|
397
|
+
"fullPage": {
|
|
398
|
+
"type": "boolean"
|
|
399
|
+
},
|
|
400
|
+
"clip": {
|
|
401
|
+
"type": "object",
|
|
402
|
+
"properties": {
|
|
403
|
+
"x": {
|
|
404
|
+
"type": "number"
|
|
405
|
+
},
|
|
406
|
+
"y": {
|
|
407
|
+
"type": "number"
|
|
408
|
+
},
|
|
409
|
+
"width": {
|
|
410
|
+
"type": "number",
|
|
411
|
+
"exclusiveMinimum": 0
|
|
412
|
+
},
|
|
413
|
+
"height": {
|
|
414
|
+
"type": "number",
|
|
415
|
+
"exclusiveMinimum": 0
|
|
416
|
+
}
|
|
417
|
+
},
|
|
418
|
+
"required": [
|
|
419
|
+
"x",
|
|
420
|
+
"y",
|
|
421
|
+
"width",
|
|
422
|
+
"height"
|
|
423
|
+
],
|
|
424
|
+
"additionalProperties": false
|
|
425
|
+
},
|
|
426
|
+
"omitBackground": {
|
|
427
|
+
"type": "boolean"
|
|
428
|
+
},
|
|
429
|
+
"encoding": {
|
|
430
|
+
"type": "string",
|
|
431
|
+
"enum": [
|
|
432
|
+
"base64",
|
|
433
|
+
"binary"
|
|
434
|
+
]
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
"additionalProperties": false
|
|
438
|
+
}
|
|
439
|
+
},
|
|
440
|
+
"required": [
|
|
441
|
+
"type",
|
|
442
|
+
"path"
|
|
443
|
+
],
|
|
444
|
+
"additionalProperties": false,
|
|
445
|
+
"description": "Take a screenshot."
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
"type": "object",
|
|
449
|
+
"properties": {
|
|
450
|
+
"type": {
|
|
451
|
+
"type": "string",
|
|
452
|
+
"const": "EVALUATE"
|
|
453
|
+
},
|
|
454
|
+
"script": {
|
|
455
|
+
"type": "string",
|
|
456
|
+
"description": "JavaScript evaluated in the page. Never interpolated."
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
"required": [
|
|
460
|
+
"type",
|
|
461
|
+
"script"
|
|
462
|
+
],
|
|
463
|
+
"additionalProperties": false,
|
|
464
|
+
"description": "Evaluate JavaScript in the page."
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
"type": "object",
|
|
468
|
+
"properties": {
|
|
469
|
+
"type": {
|
|
470
|
+
"type": "string",
|
|
471
|
+
"const": "SET_VIEWPORT"
|
|
472
|
+
},
|
|
473
|
+
"width": {
|
|
474
|
+
"type": "integer",
|
|
475
|
+
"exclusiveMinimum": 0,
|
|
476
|
+
"maximum": 9007199254740991
|
|
477
|
+
},
|
|
478
|
+
"height": {
|
|
479
|
+
"type": "integer",
|
|
480
|
+
"exclusiveMinimum": 0,
|
|
481
|
+
"maximum": 9007199254740991
|
|
482
|
+
}
|
|
483
|
+
},
|
|
484
|
+
"required": [
|
|
485
|
+
"type",
|
|
486
|
+
"width",
|
|
487
|
+
"height"
|
|
488
|
+
],
|
|
489
|
+
"additionalProperties": false,
|
|
490
|
+
"description": "Set the page viewport size."
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
"type": "object",
|
|
494
|
+
"properties": {
|
|
495
|
+
"type": {
|
|
496
|
+
"type": "string",
|
|
497
|
+
"const": "CLOSE"
|
|
498
|
+
}
|
|
499
|
+
},
|
|
500
|
+
"required": [
|
|
501
|
+
"type"
|
|
502
|
+
],
|
|
503
|
+
"additionalProperties": false,
|
|
504
|
+
"description": "Close the page."
|
|
505
|
+
}
|
|
506
|
+
]
|
|
507
|
+
}
|
|
508
|
+
]
|
|
509
|
+
}
|
|
510
|
+
},
|
|
511
|
+
"actions": {
|
|
512
|
+
"description": "Full actions, run after steps.",
|
|
513
|
+
"type": "array",
|
|
514
|
+
"items": {
|
|
515
|
+
"oneOf": [
|
|
516
|
+
{
|
|
517
|
+
"type": "object",
|
|
518
|
+
"properties": {
|
|
519
|
+
"type": {
|
|
520
|
+
"type": "string",
|
|
521
|
+
"const": "GOTO"
|
|
522
|
+
},
|
|
523
|
+
"url": {
|
|
524
|
+
"type": "string",
|
|
525
|
+
"description": "URL. \"$VAR\" as the whole value, or ${VAR} placeholders anywhere."
|
|
526
|
+
},
|
|
527
|
+
"options": {
|
|
528
|
+
"type": "object",
|
|
529
|
+
"properties": {
|
|
530
|
+
"timeout": {
|
|
531
|
+
"description": "Navigation timeout in milliseconds.",
|
|
532
|
+
"type": "integer",
|
|
533
|
+
"minimum": 0,
|
|
534
|
+
"maximum": 9007199254740991
|
|
535
|
+
},
|
|
536
|
+
"waitUntil": {
|
|
537
|
+
"description": "When to consider the navigation finished.",
|
|
538
|
+
"anyOf": [
|
|
539
|
+
{
|
|
540
|
+
"type": "string",
|
|
541
|
+
"enum": [
|
|
542
|
+
"load",
|
|
543
|
+
"domcontentloaded",
|
|
544
|
+
"networkidle0",
|
|
545
|
+
"networkidle2"
|
|
546
|
+
]
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
"type": "array",
|
|
550
|
+
"items": {
|
|
551
|
+
"type": "string",
|
|
552
|
+
"enum": [
|
|
553
|
+
"load",
|
|
554
|
+
"domcontentloaded",
|
|
555
|
+
"networkidle0",
|
|
556
|
+
"networkidle2"
|
|
557
|
+
]
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
]
|
|
561
|
+
},
|
|
562
|
+
"referer": {
|
|
563
|
+
"description": "Referer header. ${VAR} placeholders are resolved.",
|
|
564
|
+
"type": "string"
|
|
565
|
+
}
|
|
566
|
+
},
|
|
567
|
+
"additionalProperties": false
|
|
568
|
+
}
|
|
569
|
+
},
|
|
570
|
+
"required": [
|
|
571
|
+
"type",
|
|
572
|
+
"url"
|
|
573
|
+
],
|
|
574
|
+
"additionalProperties": false,
|
|
575
|
+
"description": "Navigate to a URL, with navigation options."
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
"type": "object",
|
|
579
|
+
"properties": {
|
|
580
|
+
"type": {
|
|
581
|
+
"type": "string",
|
|
582
|
+
"const": "CLICK"
|
|
583
|
+
},
|
|
584
|
+
"selector": {
|
|
585
|
+
"type": "string",
|
|
586
|
+
"description": "CSS selector, or Puppeteer selector: ::-p-xpath(...), ::-p-text(...), ::-p-aria(...), xpath/..., >>> (shadow DOM). ${VAR} placeholders are resolved."
|
|
587
|
+
},
|
|
588
|
+
"options": {
|
|
589
|
+
"type": "object",
|
|
590
|
+
"properties": {
|
|
591
|
+
"button": {
|
|
592
|
+
"type": "string",
|
|
593
|
+
"enum": [
|
|
594
|
+
"left",
|
|
595
|
+
"right",
|
|
596
|
+
"middle"
|
|
597
|
+
]
|
|
598
|
+
},
|
|
599
|
+
"clickCount": {
|
|
600
|
+
"description": "2 for a double-click.",
|
|
601
|
+
"type": "integer",
|
|
602
|
+
"exclusiveMinimum": 0,
|
|
603
|
+
"maximum": 9007199254740991
|
|
604
|
+
},
|
|
605
|
+
"delay": {
|
|
606
|
+
"description": "Milliseconds between mousedown and mouseup.",
|
|
607
|
+
"type": "integer",
|
|
608
|
+
"minimum": 0,
|
|
609
|
+
"maximum": 9007199254740991
|
|
610
|
+
}
|
|
611
|
+
},
|
|
612
|
+
"additionalProperties": false
|
|
613
|
+
}
|
|
614
|
+
},
|
|
615
|
+
"required": [
|
|
616
|
+
"type",
|
|
617
|
+
"selector"
|
|
618
|
+
],
|
|
619
|
+
"additionalProperties": false,
|
|
620
|
+
"description": "Click on an element."
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
"type": "object",
|
|
624
|
+
"properties": {
|
|
625
|
+
"type": {
|
|
626
|
+
"type": "string",
|
|
627
|
+
"const": "TYPE"
|
|
628
|
+
},
|
|
629
|
+
"selector": {
|
|
630
|
+
"type": "string",
|
|
631
|
+
"description": "CSS selector, or Puppeteer selector: ::-p-xpath(...), ::-p-text(...), ::-p-aria(...), xpath/..., >>> (shadow DOM). ${VAR} placeholders are resolved."
|
|
632
|
+
},
|
|
633
|
+
"text": {
|
|
634
|
+
"type": "string",
|
|
635
|
+
"description": "Text to type. ${VAR} placeholders are resolved (keep credentials in environment variables). Never logged."
|
|
636
|
+
},
|
|
637
|
+
"options": {
|
|
638
|
+
"type": "object",
|
|
639
|
+
"properties": {
|
|
640
|
+
"delay": {
|
|
641
|
+
"description": "Milliseconds between keystrokes.",
|
|
642
|
+
"type": "integer",
|
|
643
|
+
"minimum": 0,
|
|
644
|
+
"maximum": 9007199254740991
|
|
645
|
+
}
|
|
646
|
+
},
|
|
647
|
+
"additionalProperties": false
|
|
648
|
+
}
|
|
649
|
+
},
|
|
650
|
+
"required": [
|
|
651
|
+
"type",
|
|
652
|
+
"selector",
|
|
653
|
+
"text"
|
|
654
|
+
],
|
|
655
|
+
"additionalProperties": false,
|
|
656
|
+
"description": "Type text into an element."
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
"type": "object",
|
|
660
|
+
"properties": {
|
|
661
|
+
"type": {
|
|
662
|
+
"type": "string",
|
|
663
|
+
"const": "WAIT_FOR_SELECTOR"
|
|
664
|
+
},
|
|
665
|
+
"selector": {
|
|
666
|
+
"type": "string",
|
|
667
|
+
"description": "CSS selector, or Puppeteer selector: ::-p-xpath(...), ::-p-text(...), ::-p-aria(...), xpath/..., >>> (shadow DOM). ${VAR} placeholders are resolved."
|
|
668
|
+
},
|
|
669
|
+
"options": {
|
|
670
|
+
"type": "object",
|
|
671
|
+
"properties": {
|
|
672
|
+
"visible": {
|
|
673
|
+
"type": "boolean"
|
|
674
|
+
},
|
|
675
|
+
"hidden": {
|
|
676
|
+
"type": "boolean"
|
|
677
|
+
},
|
|
678
|
+
"timeout": {
|
|
679
|
+
"description": "Timeout in milliseconds.",
|
|
680
|
+
"type": "integer",
|
|
681
|
+
"minimum": 0,
|
|
682
|
+
"maximum": 9007199254740991
|
|
683
|
+
}
|
|
684
|
+
},
|
|
685
|
+
"additionalProperties": false
|
|
686
|
+
}
|
|
687
|
+
},
|
|
688
|
+
"required": [
|
|
689
|
+
"type",
|
|
690
|
+
"selector"
|
|
691
|
+
],
|
|
692
|
+
"additionalProperties": false,
|
|
693
|
+
"description": "Wait for an element to appear (or to be visible / hidden)."
|
|
694
|
+
},
|
|
695
|
+
{
|
|
696
|
+
"type": "object",
|
|
697
|
+
"properties": {
|
|
698
|
+
"type": {
|
|
699
|
+
"type": "string",
|
|
700
|
+
"const": "WAIT_FOR_TIMEOUT"
|
|
701
|
+
},
|
|
702
|
+
"timeout": {
|
|
703
|
+
"type": "integer",
|
|
704
|
+
"minimum": 0,
|
|
705
|
+
"maximum": 9007199254740991,
|
|
706
|
+
"description": "Milliseconds."
|
|
707
|
+
}
|
|
708
|
+
},
|
|
709
|
+
"required": [
|
|
710
|
+
"type",
|
|
711
|
+
"timeout"
|
|
712
|
+
],
|
|
713
|
+
"additionalProperties": false,
|
|
714
|
+
"description": "Wait for a duration in milliseconds."
|
|
715
|
+
},
|
|
716
|
+
{
|
|
717
|
+
"type": "object",
|
|
718
|
+
"properties": {
|
|
719
|
+
"type": {
|
|
720
|
+
"type": "string",
|
|
721
|
+
"const": "WAIT"
|
|
722
|
+
},
|
|
723
|
+
"milliseconds": {
|
|
724
|
+
"type": "integer",
|
|
725
|
+
"minimum": 0,
|
|
726
|
+
"maximum": 9007199254740991
|
|
727
|
+
}
|
|
728
|
+
},
|
|
729
|
+
"required": [
|
|
730
|
+
"type",
|
|
731
|
+
"milliseconds"
|
|
732
|
+
],
|
|
733
|
+
"additionalProperties": false,
|
|
734
|
+
"description": "Wait for a duration in milliseconds."
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
"type": "object",
|
|
738
|
+
"properties": {
|
|
739
|
+
"type": {
|
|
740
|
+
"type": "string",
|
|
741
|
+
"const": "PAUSE"
|
|
742
|
+
}
|
|
743
|
+
},
|
|
744
|
+
"required": [
|
|
745
|
+
"type"
|
|
746
|
+
],
|
|
747
|
+
"additionalProperties": false,
|
|
748
|
+
"description": "Wait for Enter in an interactive terminal (debugging). Ignored with a warning when there is none."
|
|
749
|
+
},
|
|
750
|
+
{
|
|
751
|
+
"type": "object",
|
|
752
|
+
"properties": {
|
|
753
|
+
"type": {
|
|
754
|
+
"type": "string",
|
|
755
|
+
"const": "SCREENSHOT"
|
|
756
|
+
},
|
|
757
|
+
"path": {
|
|
758
|
+
"type": "string",
|
|
759
|
+
"description": "File path. \"$VAR\" as the whole value, or ${VAR} placeholders anywhere."
|
|
760
|
+
},
|
|
761
|
+
"options": {
|
|
762
|
+
"type": "object",
|
|
763
|
+
"properties": {
|
|
764
|
+
"type": {
|
|
765
|
+
"type": "string",
|
|
766
|
+
"enum": [
|
|
767
|
+
"png",
|
|
768
|
+
"jpeg"
|
|
769
|
+
]
|
|
770
|
+
},
|
|
771
|
+
"quality": {
|
|
772
|
+
"description": "JPEG quality (0-100).",
|
|
773
|
+
"type": "integer",
|
|
774
|
+
"minimum": 0,
|
|
775
|
+
"maximum": 100
|
|
776
|
+
},
|
|
777
|
+
"fullPage": {
|
|
778
|
+
"type": "boolean"
|
|
779
|
+
},
|
|
780
|
+
"clip": {
|
|
781
|
+
"type": "object",
|
|
782
|
+
"properties": {
|
|
783
|
+
"x": {
|
|
784
|
+
"type": "number"
|
|
785
|
+
},
|
|
786
|
+
"y": {
|
|
787
|
+
"type": "number"
|
|
788
|
+
},
|
|
789
|
+
"width": {
|
|
790
|
+
"type": "number",
|
|
791
|
+
"exclusiveMinimum": 0
|
|
792
|
+
},
|
|
793
|
+
"height": {
|
|
794
|
+
"type": "number",
|
|
795
|
+
"exclusiveMinimum": 0
|
|
796
|
+
}
|
|
797
|
+
},
|
|
798
|
+
"required": [
|
|
799
|
+
"x",
|
|
800
|
+
"y",
|
|
801
|
+
"width",
|
|
802
|
+
"height"
|
|
803
|
+
],
|
|
804
|
+
"additionalProperties": false
|
|
805
|
+
},
|
|
806
|
+
"omitBackground": {
|
|
807
|
+
"type": "boolean"
|
|
808
|
+
},
|
|
809
|
+
"encoding": {
|
|
810
|
+
"type": "string",
|
|
811
|
+
"enum": [
|
|
812
|
+
"base64",
|
|
813
|
+
"binary"
|
|
814
|
+
]
|
|
815
|
+
}
|
|
816
|
+
},
|
|
817
|
+
"additionalProperties": false
|
|
818
|
+
}
|
|
819
|
+
},
|
|
820
|
+
"required": [
|
|
821
|
+
"type",
|
|
822
|
+
"path"
|
|
823
|
+
],
|
|
824
|
+
"additionalProperties": false,
|
|
825
|
+
"description": "Take a screenshot."
|
|
826
|
+
},
|
|
827
|
+
{
|
|
828
|
+
"type": "object",
|
|
829
|
+
"properties": {
|
|
830
|
+
"type": {
|
|
831
|
+
"type": "string",
|
|
832
|
+
"const": "EVALUATE"
|
|
833
|
+
},
|
|
834
|
+
"script": {
|
|
835
|
+
"type": "string",
|
|
836
|
+
"description": "JavaScript evaluated in the page. Never interpolated."
|
|
837
|
+
}
|
|
838
|
+
},
|
|
839
|
+
"required": [
|
|
840
|
+
"type",
|
|
841
|
+
"script"
|
|
842
|
+
],
|
|
843
|
+
"additionalProperties": false,
|
|
844
|
+
"description": "Evaluate JavaScript in the page."
|
|
845
|
+
},
|
|
846
|
+
{
|
|
847
|
+
"type": "object",
|
|
848
|
+
"properties": {
|
|
849
|
+
"type": {
|
|
850
|
+
"type": "string",
|
|
851
|
+
"const": "SET_VIEWPORT"
|
|
852
|
+
},
|
|
853
|
+
"width": {
|
|
854
|
+
"type": "integer",
|
|
855
|
+
"exclusiveMinimum": 0,
|
|
856
|
+
"maximum": 9007199254740991
|
|
857
|
+
},
|
|
858
|
+
"height": {
|
|
859
|
+
"type": "integer",
|
|
860
|
+
"exclusiveMinimum": 0,
|
|
861
|
+
"maximum": 9007199254740991
|
|
862
|
+
}
|
|
863
|
+
},
|
|
864
|
+
"required": [
|
|
865
|
+
"type",
|
|
866
|
+
"width",
|
|
867
|
+
"height"
|
|
868
|
+
],
|
|
869
|
+
"additionalProperties": false,
|
|
870
|
+
"description": "Set the page viewport size."
|
|
871
|
+
},
|
|
872
|
+
{
|
|
873
|
+
"type": "object",
|
|
874
|
+
"properties": {
|
|
875
|
+
"type": {
|
|
876
|
+
"type": "string",
|
|
877
|
+
"const": "CLOSE"
|
|
878
|
+
}
|
|
879
|
+
},
|
|
880
|
+
"required": [
|
|
881
|
+
"type"
|
|
882
|
+
],
|
|
883
|
+
"additionalProperties": false,
|
|
884
|
+
"description": "Close the page."
|
|
885
|
+
}
|
|
886
|
+
]
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
},
|
|
890
|
+
"additionalProperties": false,
|
|
891
|
+
"description": "A population of users: its workers run the steps and actions for the given number of iterations."
|
|
892
|
+
},
|
|
893
|
+
"description": "Scenarios, all started at the same time."
|
|
894
|
+
}
|
|
895
|
+
},
|
|
896
|
+
"required": [
|
|
897
|
+
"scenarios"
|
|
898
|
+
],
|
|
899
|
+
"additionalProperties": false
|
|
900
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schema (draft 2020-12) of the YAML configuration, generated from the
|
|
3
|
+
* zod schema used at runtime, so both always agree. Published as
|
|
4
|
+
* `dist/schema.json` for editors (completion, hover documentation, validation).
|
|
5
|
+
*/
|
|
6
|
+
export declare const buildJsonSchema: () => Record<string, unknown>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bloom-perf/yaml-pptr",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "A library to generate puppeteer browser controls through a YAML api.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"@types/chai": "5.2.3",
|
|
16
16
|
"@types/mocha": "10.0.10",
|
|
17
17
|
"@types/node": "22.20.5",
|
|
18
|
+
"ajv": "8.20.0",
|
|
18
19
|
"c8": "12.0.0",
|
|
19
20
|
"chai": "6.3.0",
|
|
20
21
|
"esbuild": "0.28.2",
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
"puppeteer": "^25.0.0"
|
|
34
35
|
},
|
|
35
36
|
"scripts": {
|
|
36
|
-
"build": "rm -rf dist && node esbuild.js && tsc -p tsconfig.build.json",
|
|
37
|
+
"build": "rm -rf dist && node esbuild.js && tsc -p tsconfig.build.json && tsx scripts/generate-schema.ts",
|
|
37
38
|
"typecheck": "tsc -p tsconfig.json",
|
|
38
39
|
"test": "mocha",
|
|
39
40
|
"test:coverage": "c8 mocha",
|