@stubber/virtual-worker 1.0.6 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/commands/browser/browser_click.js +2 -11
- package/app/commands/browser/browser_extract_data.js +1 -1
- package/app/commands/browser/browser_extract_html.js +1 -1
- package/app/commands/browser/browser_get_clipboard_text.js +39 -0
- package/app/commands/browser/browser_get_localstorage.js +2 -3
- package/app/commands/browser/browser_navigate.js +3 -3
- package/app/commands/browser/browser_press_key.js +3 -6
- package/app/commands/browser/browser_screenshot.js +4 -2
- package/app/commands/browser/browser_write_text.js +3 -6
- package/app/commands/index.js +2 -0
- package/app/helpers/get_chromium_page.js +9 -8
- package/package.json +1 -1
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { create_error_conceptual } from "#app/functions/create_error_conceptual.js";
|
|
2
|
-
import { create_error_technical } from "#app/functions/create_error_technical.js";
|
|
3
2
|
import { create_success } from "#app/functions/create_success.js";
|
|
4
|
-
import { get_chromium_page } from "../../helpers/get_chromium_page.js";
|
|
5
3
|
import fs from "fs";
|
|
6
4
|
import { v4 } from "uuid";
|
|
5
|
+
import { get_chromium_page } from "../../helpers/get_chromium_page.js";
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
*
|
|
@@ -16,7 +15,7 @@ export const browser_click = async (params, stubber_context) => {
|
|
|
16
15
|
const { entries } = params || {};
|
|
17
16
|
|
|
18
17
|
// use playwright to move the mouse and perform a left click
|
|
19
|
-
const page_result = await get_chromium_page(stubber_context.stubref);
|
|
18
|
+
const page_result = await get_chromium_page(params?.session_id || stubber_context.stubref);
|
|
20
19
|
|
|
21
20
|
if (!page_result.success) {
|
|
22
21
|
return page_result;
|
|
@@ -40,14 +39,6 @@ export const browser_click = async (params, stubber_context) => {
|
|
|
40
39
|
target = page.locator(locator);
|
|
41
40
|
}
|
|
42
41
|
|
|
43
|
-
// const target = page.locator(locator);
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
await target.waitFor({ state: "attached", timeout: 5000 });
|
|
47
|
-
} catch {
|
|
48
|
-
return create_error_conceptual({ message: "No element found for locator", details: { locator, frame } });
|
|
49
|
-
}
|
|
50
|
-
|
|
51
42
|
if (download) {
|
|
52
43
|
// not all downloads are made equal. Some of them actually trigger the "download" event, in which case playwright handles it
|
|
53
44
|
// however, some files, like PDFs, are opened inline in the browser, so no download event is triggered
|
|
@@ -9,7 +9,7 @@ export const browser_extract_data = async (params, stubber_context) => {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
// Get the Chromium page
|
|
12
|
-
const page_result = await get_chromium_page(stubber_context.stubref);
|
|
12
|
+
const page_result = await get_chromium_page(params?.session_id || stubber_context.stubref);
|
|
13
13
|
if (!page_result.success) {
|
|
14
14
|
return page_result;
|
|
15
15
|
}
|
|
@@ -10,7 +10,7 @@ import { get_chromium_page } from "../../helpers/get_chromium_page.js";
|
|
|
10
10
|
*/
|
|
11
11
|
export const browser_extract_html = async (params, stubber_context) => {
|
|
12
12
|
// Get the Chromium page
|
|
13
|
-
const page_result = await get_chromium_page(stubber_context.stubref);
|
|
13
|
+
const page_result = await get_chromium_page(params?.session_id || stubber_context.stubref);
|
|
14
14
|
if (!page_result.success) {
|
|
15
15
|
return page_result;
|
|
16
16
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { create_error_conceptual } from "#app/functions/create_error_conceptual.js";
|
|
2
|
+
import { create_error_technical } from "#app/functions/create_error_technical.js";
|
|
3
|
+
import { create_success } from "#app/functions/create_success.js";
|
|
4
|
+
import { get_chromium_page } from "../../helpers/get_chromium_page.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Reads text from the system clipboard for the page's origin.
|
|
8
|
+
* Playwright sometimes requires permissions to use the Clipboard API; this tries to
|
|
9
|
+
* request clipboard-read permission for the page's origin before reading.
|
|
10
|
+
*
|
|
11
|
+
* @param {Object} params
|
|
12
|
+
* @param {string} [params.session_id] - optional session id for get_chromium_page
|
|
13
|
+
* @returns
|
|
14
|
+
*/
|
|
15
|
+
export const browser_get_clipboard_text = async (params, stubber_context) => {
|
|
16
|
+
const page_result = await get_chromium_page(params?.session_id || stubber_context.stubref);
|
|
17
|
+
|
|
18
|
+
if (!page_result.success) {
|
|
19
|
+
return page_result;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const page = page_result.payload;
|
|
23
|
+
|
|
24
|
+
const page_url = page.url();
|
|
25
|
+
|
|
26
|
+
if (!page_url || page_url === "about:blank") {
|
|
27
|
+
return create_error_conceptual({ message: "No page loaded", details: { url: page_url } });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// This will attempt to read the clipboard using the browser API.
|
|
31
|
+
// Some environments require user gesture or extra permissions; handle failures.
|
|
32
|
+
const text = await page.evaluate(async () => {
|
|
33
|
+
/* global navigator */
|
|
34
|
+
// navigator.clipboard.readText might throw if permission is denied
|
|
35
|
+
return await navigator.clipboard.readText();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return create_success({ message: "Clipboard text retrieved successfully", payload: { text } });
|
|
39
|
+
};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { create_error_conceptual } from "#app/functions/create_error_conceptual.js";
|
|
2
|
-
import { create_error_technical } from "#app/functions/create_error_technical.js";
|
|
3
2
|
import { create_success } from "#app/functions/create_success.js";
|
|
4
3
|
import { get_chromium_page } from "../../helpers/get_chromium_page.js";
|
|
5
4
|
|
|
6
|
-
export const browser_get_localstorage = async (
|
|
7
|
-
const page_result = await get_chromium_page(stubber_context.stubref);
|
|
5
|
+
export const browser_get_localstorage = async (params, stubber_context) => {
|
|
6
|
+
const page_result = await get_chromium_page(params?.session_id || stubber_context.stubref);
|
|
8
7
|
|
|
9
8
|
if (!page_result.success) {
|
|
10
9
|
return page_result;
|
|
@@ -3,16 +3,16 @@ import { create_success } from "#app/functions/create_success.js";
|
|
|
3
3
|
import { get_chromium_page } from "../../helpers/get_chromium_page.js";
|
|
4
4
|
|
|
5
5
|
export const browser_navigate = async (params, stubber_context) => {
|
|
6
|
-
const result = await get_chromium_page(stubber_context.stubref);
|
|
6
|
+
const result = await get_chromium_page(params?.session_id || stubber_context.stubref);
|
|
7
7
|
if (!result.success) {
|
|
8
8
|
return result;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
const { url } = params || {};
|
|
11
|
+
const { url, options } = params || {};
|
|
12
12
|
|
|
13
13
|
const page = result.payload;
|
|
14
14
|
|
|
15
|
-
if (url) await page.goto(url);
|
|
15
|
+
if (url) await page.goto(url, options);
|
|
16
16
|
|
|
17
17
|
return create_success({ message: "Navigated to new page", payload: {} });
|
|
18
18
|
};
|
|
@@ -9,8 +9,9 @@ import { get_chromium_page } from "#app/helpers/get_chromium_page.js";
|
|
|
9
9
|
* @param {Array<{locator?: string, frame?:string, key?: string, keys?: string}>} params.entries - Array of locator and key pairs.
|
|
10
10
|
* @returns
|
|
11
11
|
*/
|
|
12
|
-
export const browser_press_key = async (
|
|
13
|
-
const
|
|
12
|
+
export const browser_press_key = async (params, stubber_context) => {
|
|
13
|
+
const { entries } = params || {};
|
|
14
|
+
const page_result = await get_chromium_page(params?.session_id || stubber_context.stubref);
|
|
14
15
|
if (!page_result.success) {
|
|
15
16
|
return page_result;
|
|
16
17
|
}
|
|
@@ -43,10 +44,6 @@ export const browser_press_key = async ({ entries }, stubber_context) => {
|
|
|
43
44
|
target = page.locator(locator);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
if (!(await target.count())) {
|
|
47
|
-
return create_error_conceptual({ message: "No element found for locator", details: { locator, key, keys } });
|
|
48
|
-
}
|
|
49
|
-
|
|
50
47
|
if (key) {
|
|
51
48
|
await target.press(key);
|
|
52
49
|
} else if (keys) {
|
|
@@ -11,8 +11,10 @@ import { create_error_technical } from "#app/functions/create_error_technical.js
|
|
|
11
11
|
* @param {string} [params.locator] - Optional locator to screenshot a specific element
|
|
12
12
|
* @returns
|
|
13
13
|
*/
|
|
14
|
-
export const browser_screenshot = async (
|
|
15
|
-
|
|
14
|
+
export const browser_screenshot = async (params, stubber_context) => {
|
|
15
|
+
let { screenshot_options, locator } = params || {};
|
|
16
|
+
|
|
17
|
+
const page_result = await get_chromium_page(params?.session_id || stubber_context.stubref);
|
|
16
18
|
if (!page_result.success) {
|
|
17
19
|
return page_result;
|
|
18
20
|
}
|
|
@@ -9,8 +9,9 @@ import { get_chromium_page } from "../../helpers/get_chromium_page.js";
|
|
|
9
9
|
* @param {Array<{locator: string, frame?:string, text: string}>} params.entries - Array of locator and text pairs.
|
|
10
10
|
* @returns
|
|
11
11
|
*/
|
|
12
|
-
export const browser_write_text = async (
|
|
13
|
-
const
|
|
12
|
+
export const browser_write_text = async (params, stubber_context) => {
|
|
13
|
+
const { entries } = params || {};
|
|
14
|
+
const page_result = await get_chromium_page(params?.session_id || stubber_context.stubref);
|
|
14
15
|
if (!page_result.success) {
|
|
15
16
|
return page_result;
|
|
16
17
|
}
|
|
@@ -40,10 +41,6 @@ export const browser_write_text = async ({ entries }, stubber_context) => {
|
|
|
40
41
|
target = page.locator(locator);
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
if (!(await target.count())) {
|
|
44
|
-
return create_error_conceptual({ message: "No element found for locator", details: { locator, text } });
|
|
45
|
-
}
|
|
46
|
-
|
|
47
44
|
await target.fill(text);
|
|
48
45
|
}
|
|
49
46
|
|
package/app/commands/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { browser_write_text } from "./browser/browser_write_text.js";
|
|
|
6
6
|
import { browser_press_key } from "./browser/browser_press_key.js";
|
|
7
7
|
import { browser_extract_html } from "./browser/browser_extract_html.js";
|
|
8
8
|
import { browser_screenshot } from "./browser/browser_screenshot.js";
|
|
9
|
+
import { browser_get_clipboard_text } from "./browser/browser_get_clipboard_text.js";
|
|
9
10
|
import { cli_run } from "./cli/cli_run.js";
|
|
10
11
|
|
|
11
12
|
import { upload_files } from "./file-server/upload_files.js";
|
|
@@ -20,6 +21,7 @@ const all_commands = {
|
|
|
20
21
|
browser_press_key,
|
|
21
22
|
browser_extract_html,
|
|
22
23
|
browser_screenshot,
|
|
24
|
+
browser_get_clipboard_text,
|
|
23
25
|
|
|
24
26
|
cli_run,
|
|
25
27
|
|
|
@@ -13,12 +13,12 @@ let browser;
|
|
|
13
13
|
const contexts = {};
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* @param {string}
|
|
16
|
+
* @param {string} session_id
|
|
17
17
|
* @returns {Promise<{ success: boolean, payload?: import("playwright").Page }>}
|
|
18
18
|
*/
|
|
19
|
-
export const get_chromium_page = async (
|
|
20
|
-
if (!
|
|
21
|
-
return create_error_conceptual({ message: "
|
|
19
|
+
export const get_chromium_page = async (session_id) => {
|
|
20
|
+
if (!session_id) {
|
|
21
|
+
return create_error_conceptual({ message: "session_id is required to get a Chromium page." });
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
// Launch the browser once and reuse it
|
|
@@ -26,22 +26,23 @@ export const get_chromium_page = async (stubref) => {
|
|
|
26
26
|
browser = await chromium.launch({
|
|
27
27
|
headless: false,
|
|
28
28
|
// eslint-disable-next-line id-match
|
|
29
|
-
slowMo:
|
|
29
|
+
slowMo: 500,
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
// Create a new context per stubref if not already created
|
|
34
|
-
if (!contexts[
|
|
34
|
+
if (!contexts[session_id]) {
|
|
35
35
|
const context = await browser.newContext({
|
|
36
36
|
// eslint-disable-next-line id-match
|
|
37
37
|
ignoreHTTPSErrors: true,
|
|
38
|
+
permissions: ["clipboard-read", "clipboard-write"],
|
|
38
39
|
});
|
|
39
|
-
contexts[
|
|
40
|
+
contexts[session_id] = {
|
|
40
41
|
context,
|
|
41
42
|
};
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
const context = contexts[
|
|
45
|
+
const context = contexts[session_id].context;
|
|
45
46
|
|
|
46
47
|
// Try to find an open page in the context
|
|
47
48
|
let page = context.pages().find((p) => !p.isClosed());
|