@putdotio/rokit 1.2.0 → 1.3.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 +10 -2
- package/dist/index.d.mts +7 -1
- package/dist/index.mjs +2 -2
- package/dist/rokit.mjs +1 -1
- package/dist/{roku-DxlYPbY1.mjs → roku-7hiM97p0.mjs} +32 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,7 +47,13 @@ pnpm exec rokit screenshot artifacts/live/player.png
|
|
|
47
47
|
App-specific scenario scripts can also import the generic helpers:
|
|
48
48
|
|
|
49
49
|
```ts
|
|
50
|
-
import {
|
|
50
|
+
import {
|
|
51
|
+
assertSceneGraphNode,
|
|
52
|
+
pressKey,
|
|
53
|
+
querySceneGraph,
|
|
54
|
+
readNamedNodeTranslation,
|
|
55
|
+
type RokuContext,
|
|
56
|
+
} from "@putdotio/rokit";
|
|
51
57
|
|
|
52
58
|
const target = process.env.ROKIT_TARGET;
|
|
53
59
|
|
|
@@ -62,8 +68,9 @@ const context: RokuContext = {
|
|
|
62
68
|
};
|
|
63
69
|
|
|
64
70
|
await pressKey(context, "Info");
|
|
71
|
+
const xml = await querySceneGraph(context, { attempts: 3 });
|
|
65
72
|
await assertSceneGraphNode(context, "videoPlayerScreen", { state: "visible" });
|
|
66
|
-
|
|
73
|
+
console.log(readNamedNodeTranslation(xml, "videoPlayerScreen"));
|
|
67
74
|
```
|
|
68
75
|
|
|
69
76
|
## Commands
|
|
@@ -130,6 +137,7 @@ tokens, and app-specific media identifiers do not belong in git.
|
|
|
130
137
|
- remote keypresses
|
|
131
138
|
- raw ECP queries
|
|
132
139
|
- SceneGraph state queries and named-node assertions
|
|
140
|
+
- SceneGraph attribute, numeric geometry, bounds, and translation readers
|
|
133
141
|
- screenshots
|
|
134
142
|
|
|
135
143
|
App repositories should keep their own scenario commands for product behavior,
|
package/dist/index.d.mts
CHANGED
|
@@ -2,6 +2,8 @@ import * as rokuDeploy from "roku-deploy";
|
|
|
2
2
|
|
|
3
3
|
//#region src/scenegraph.d.ts
|
|
4
4
|
type NodeState = "absent" | "hidden" | "visible";
|
|
5
|
+
type SceneGraphBounds = readonly [x: number, y: number, width: number, height: number];
|
|
6
|
+
type SceneGraphPoint = readonly [x: number, y: number];
|
|
5
7
|
type NodeExpectation = {
|
|
6
8
|
readonly state: NodeState;
|
|
7
9
|
readonly text?: string;
|
|
@@ -11,10 +13,14 @@ type NodeExpectation = {
|
|
|
11
13
|
};
|
|
12
14
|
declare const readNamedNodeAttributes: (xml: string, nodeName: string) => string | undefined;
|
|
13
15
|
declare const readNamedNodeAttribute: (xml: string, nodeName: string, attributeName: string) => string | undefined;
|
|
16
|
+
declare const readNamedNodeNumber: (xml: string, nodeName: string, attributeName: string) => number | undefined;
|
|
17
|
+
declare const readNamedNodeBounds: (xml: string, nodeName: string) => SceneGraphBounds | undefined;
|
|
18
|
+
declare const readNamedNodeTranslation: (xml: string, nodeName: string) => SceneGraphPoint | undefined;
|
|
14
19
|
declare const isNamedNodeVisible: (xml: string, nodeName: string) => boolean;
|
|
15
20
|
declare const assertNamedNode: (xml: string, nodeName: string, expectation: NodeExpectation) => void;
|
|
16
21
|
declare const assertNamedNodeState: (xml: string, nodeName: string, state: NodeState) => void;
|
|
17
22
|
declare const assertNamedNodeText: (xml: string, nodeName: string, expectedText: string) => void;
|
|
23
|
+
declare const parseSceneGraphNumberList: (value: string) => number[];
|
|
18
24
|
//#endregion
|
|
19
25
|
//#region src/xml.d.ts
|
|
20
26
|
type ActiveApp = {
|
|
@@ -64,4 +70,4 @@ declare const takeScreenshot: (context: RokuContext & {
|
|
|
64
70
|
}, outputPath: string) => Promise<string>;
|
|
65
71
|
declare const validateRemoteKey: (key: string) => void;
|
|
66
72
|
//#endregion
|
|
67
|
-
export { type ActiveApp, type DeviceSummary, type NodeExpectation, type NodeState, type RemoteKey, type RetryOptions, type RokuContext, assertNamedNode, assertNamedNodeState, assertNamedNodeText, assertSceneGraphNode, checkDevice, getDeviceInfo, installPackage, isNamedNodeVisible, launchApp, pressKey, queryActiveApp, queryEcp, querySceneGraph, readActiveApp, readNamedNodeAttribute, readNamedNodeAttributes, readXmlAttribute, readXmlTag, takeScreenshot, validateRemoteKey, waitForActiveApp, waitForSceneGraphNode };
|
|
73
|
+
export { type ActiveApp, type DeviceSummary, type NodeExpectation, type NodeState, type RemoteKey, type RetryOptions, type RokuContext, type SceneGraphBounds, type SceneGraphPoint, assertNamedNode, assertNamedNodeState, assertNamedNodeText, assertSceneGraphNode, checkDevice, getDeviceInfo, installPackage, isNamedNodeVisible, launchApp, parseSceneGraphNumberList, pressKey, queryActiveApp, queryEcp, querySceneGraph, readActiveApp, readNamedNodeAttribute, readNamedNodeAttributes, readNamedNodeBounds, readNamedNodeNumber, readNamedNodeTranslation, readXmlAttribute, readXmlTag, takeScreenshot, validateRemoteKey, waitForActiveApp, waitForSceneGraphNode };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { assertNamedNode, assertNamedNodeState, assertNamedNodeText, assertSceneGraphNode, checkDevice, getDeviceInfo, installPackage, isNamedNodeVisible, launchApp, pressKey, queryActiveApp, queryEcp, querySceneGraph, readActiveApp, readNamedNodeAttribute, readNamedNodeAttributes, readXmlAttribute, readXmlTag, takeScreenshot, validateRemoteKey, waitForActiveApp, waitForSceneGraphNode };
|
|
1
|
+
import { C as readNamedNodeTranslation, E as readXmlTag, S as readNamedNodeNumber, T as readXmlAttribute, _ as isNamedNodeVisible, a as launchApp, b as readNamedNodeAttributes, c as queryEcp, d as validateRemoteKey, f as waitForActiveApp, g as assertNamedNodeText, h as assertNamedNodeState, i as installPackage, l as querySceneGraph, m as assertNamedNode, n as checkDevice, o as pressKey, p as waitForSceneGraphNode, r as getDeviceInfo, s as queryActiveApp, t as assertSceneGraphNode, u as takeScreenshot, v as parseSceneGraphNumberList, w as readActiveApp, x as readNamedNodeBounds, y as readNamedNodeAttribute } from "./roku-7hiM97p0.mjs";
|
|
2
|
+
export { assertNamedNode, assertNamedNodeState, assertNamedNodeText, assertSceneGraphNode, checkDevice, getDeviceInfo, installPackage, isNamedNodeVisible, launchApp, parseSceneGraphNumberList, pressKey, queryActiveApp, queryEcp, querySceneGraph, readActiveApp, readNamedNodeAttribute, readNamedNodeAttributes, readNamedNodeBounds, readNamedNodeNumber, readNamedNodeTranslation, readXmlAttribute, readXmlTag, takeScreenshot, validateRemoteKey, waitForActiveApp, waitForSceneGraphNode };
|
package/dist/rokit.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as launchApp, c as queryEcp, f as waitForActiveApp, i as installPackage, l as querySceneGraph, n as checkDevice, o as pressKey, p as waitForSceneGraphNode, r as getDeviceInfo, s as queryActiveApp, t as assertSceneGraphNode, u as takeScreenshot } from "./roku-
|
|
2
|
+
import { a as launchApp, c as queryEcp, f as waitForActiveApp, i as installPackage, l as querySceneGraph, n as checkDevice, o as pressKey, p as waitForSceneGraphNode, r as getDeviceInfo, s as queryActiveApp, t as assertSceneGraphNode, u as takeScreenshot } from "./roku-7hiM97p0.mjs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { existsSync, mkdirSync } from "node:fs";
|
|
@@ -28,6 +28,36 @@ const readNamedNodeAttribute = (xml, nodeName, attributeName) => {
|
|
|
28
28
|
if (!attributes) return;
|
|
29
29
|
return readXmlAttribute(attributes, attributeName);
|
|
30
30
|
};
|
|
31
|
+
const readNamedNodeNumber = (xml, nodeName, attributeName) => {
|
|
32
|
+
const value = readNamedNodeAttribute(xml, nodeName, attributeName);
|
|
33
|
+
if (value !== void 0) {
|
|
34
|
+
const parsed = Number(value);
|
|
35
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
36
|
+
}
|
|
37
|
+
if (attributeName !== "width" && attributeName !== "height") return;
|
|
38
|
+
const bounds = readNamedNodeBounds(xml, nodeName);
|
|
39
|
+
if (!bounds) return;
|
|
40
|
+
return attributeName === "width" ? bounds[2] : bounds[3];
|
|
41
|
+
};
|
|
42
|
+
const readNamedNodeBounds = (xml, nodeName) => {
|
|
43
|
+
const bounds = readNamedNodeAttribute(xml, nodeName, "bounds");
|
|
44
|
+
if (!bounds) return;
|
|
45
|
+
const parts = parseSceneGraphNumberList(bounds);
|
|
46
|
+
if (parts.length < 4) return;
|
|
47
|
+
return [
|
|
48
|
+
parts[0],
|
|
49
|
+
parts[1],
|
|
50
|
+
parts[2],
|
|
51
|
+
parts[3]
|
|
52
|
+
];
|
|
53
|
+
};
|
|
54
|
+
const readNamedNodeTranslation = (xml, nodeName) => {
|
|
55
|
+
const translation = readNamedNodeAttribute(xml, nodeName, "translation");
|
|
56
|
+
if (!translation) return;
|
|
57
|
+
const parts = parseSceneGraphNumberList(translation);
|
|
58
|
+
if (parts.length < 2) return;
|
|
59
|
+
return [parts[0], parts[1]];
|
|
60
|
+
};
|
|
31
61
|
const isNamedNodeVisible = (xml, nodeName) => {
|
|
32
62
|
const attributes = readNamedNodeAttributes(xml, nodeName);
|
|
33
63
|
return attributes !== void 0 && !attributes.includes("visible=\"false\"");
|
|
@@ -59,6 +89,7 @@ const assertNamedNodeAttribute = (xml, nodeName, attributeName, expectedValue) =
|
|
|
59
89
|
if (value !== expectedValue) throw new Error(`expected "${nodeName}" ${attributeName} "${expectedValue}", got "${value ?? "missing"}"`);
|
|
60
90
|
};
|
|
61
91
|
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
92
|
+
const parseSceneGraphNumberList = (value) => value.replace(/[[\]{}]/g, "").split(",").map((part) => Number(part.trim())).filter((part) => Number.isFinite(part));
|
|
62
93
|
//#endregion
|
|
63
94
|
//#region src/roku.ts
|
|
64
95
|
const ecpPort = 8060;
|
|
@@ -227,4 +258,4 @@ const sleep = (ms) => new Promise((resolve) => {
|
|
|
227
258
|
});
|
|
228
259
|
const formatErrorMessage = (error) => error instanceof Error ? error.message : String(error);
|
|
229
260
|
//#endregion
|
|
230
|
-
export { readXmlTag as S, isNamedNodeVisible as _, launchApp as a,
|
|
261
|
+
export { readNamedNodeTranslation as C, readXmlTag as E, readNamedNodeNumber as S, readXmlAttribute as T, isNamedNodeVisible as _, launchApp as a, readNamedNodeAttributes as b, queryEcp as c, validateRemoteKey as d, waitForActiveApp as f, assertNamedNodeText as g, assertNamedNodeState as h, installPackage as i, querySceneGraph as l, assertNamedNode as m, checkDevice as n, pressKey as o, waitForSceneGraphNode as p, getDeviceInfo as r, queryActiveApp as s, assertSceneGraphNode as t, takeScreenshot as u, parseSceneGraphNumberList as v, readActiveApp as w, readNamedNodeBounds as x, readNamedNodeAttribute as y };
|