@specsage/cli 0.1.17 → 0.1.18
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/lib/browser.js +4 -1
- package/lib/runner.rb +23 -27
- package/lib/step_client.rb +2 -1
- package/package.json +1 -1
package/lib/browser.js
CHANGED
|
@@ -704,6 +704,7 @@ const DIALOG_BLOCKING_COMMANDS = ['navigate', 'click_element', 'select_option',
|
|
|
704
704
|
|
|
705
705
|
async function handleCommand(msg) {
|
|
706
706
|
const { request_id, command, params } = msg;
|
|
707
|
+
const startTime = Date.now();
|
|
707
708
|
|
|
708
709
|
try {
|
|
709
710
|
let result = {};
|
|
@@ -1136,13 +1137,15 @@ async function handleCommand(msg) {
|
|
|
1136
1137
|
}
|
|
1137
1138
|
}
|
|
1138
1139
|
|
|
1140
|
+
if (page) result.page_url = page.url();
|
|
1141
|
+
result.duration_ms = Date.now() - startTime;
|
|
1139
1142
|
send({ request_id, ok: true, result, error: null });
|
|
1140
1143
|
|
|
1141
1144
|
} catch (err) {
|
|
1142
1145
|
send({
|
|
1143
1146
|
request_id,
|
|
1144
1147
|
ok: false,
|
|
1145
|
-
result: {},
|
|
1148
|
+
result: { duration_ms: Date.now() - startTime },
|
|
1146
1149
|
error: {
|
|
1147
1150
|
code: "BROWSER_ERROR",
|
|
1148
1151
|
message: err.message
|
package/lib/runner.rb
CHANGED
|
@@ -157,6 +157,7 @@ class Runner
|
|
|
157
157
|
interactive_elements_by_id = build_elements_by_id(interactive_elements)
|
|
158
158
|
previous_action = nil
|
|
159
159
|
action_result = nil
|
|
160
|
+
browser_result = nil
|
|
160
161
|
|
|
161
162
|
# Reset credentials and max_steps for each scenario (each has its own)
|
|
162
163
|
scenario_credentials = {}
|
|
@@ -175,6 +176,7 @@ class Runner
|
|
|
175
176
|
elements: interactive_elements,
|
|
176
177
|
previous_action: previous_action,
|
|
177
178
|
action_result: action_result,
|
|
179
|
+
browser_result: browser_result,
|
|
178
180
|
pre_scenario_for_id: pre_scenario_for_id,
|
|
179
181
|
execution_order: execution_order
|
|
180
182
|
)
|
|
@@ -231,6 +233,7 @@ class Runner
|
|
|
231
233
|
|
|
232
234
|
previous_action = action
|
|
233
235
|
action_result = result[:result]
|
|
236
|
+
browser_result = { page_url: result[:page_url], duration_ms: result[:duration_ms] }
|
|
234
237
|
|
|
235
238
|
# Check if step count has reached max_steps limit
|
|
236
239
|
step_number = step_result[:step_number] || 0
|
|
@@ -505,16 +508,12 @@ class Runner
|
|
|
505
508
|
url = substitute_credentials(url) if contains_credential_placeholder?(url)
|
|
506
509
|
|
|
507
510
|
response = send_to_node('navigate', { url: url }, eval_capture_data: eval_capture_data)
|
|
508
|
-
|
|
509
|
-
elements = response.dig('result', 'elements') || []
|
|
510
|
-
{ result: "Navigated to #{display_url}", screenshot_base64: screenshot_base64, elements: elements }
|
|
511
|
+
extract_result(response, "Navigated to #{display_url}")
|
|
511
512
|
|
|
512
513
|
when 'click'
|
|
513
514
|
element_id = action['element_id']
|
|
514
515
|
response = send_to_node('click_element', { element_id: element_id }, eval_capture_data: eval_capture_data)
|
|
515
|
-
|
|
516
|
-
elements = response.dig('result', 'elements') || []
|
|
517
|
-
{ result: "Clicked element #{element_id}", screenshot_base64: screenshot_base64, elements: elements }
|
|
516
|
+
extract_result(response, "Clicked element #{element_id}")
|
|
518
517
|
|
|
519
518
|
when 'select'
|
|
520
519
|
element_id = action['element_id']
|
|
@@ -523,9 +522,7 @@ class Runner
|
|
|
523
522
|
value = substitute_credentials(value) if contains_credential_placeholder?(value)
|
|
524
523
|
|
|
525
524
|
response = send_to_node('select_option', { element_id: element_id, value: value }, eval_capture_data: eval_capture_data)
|
|
526
|
-
|
|
527
|
-
elements = response.dig('result', 'elements') || []
|
|
528
|
-
{ result: "Selected '#{display_value}' in element #{element_id}", screenshot_base64: screenshot_base64, elements: elements }
|
|
525
|
+
extract_result(response, "Selected '#{display_value}' in element #{element_id}")
|
|
529
526
|
|
|
530
527
|
when 'type'
|
|
531
528
|
# Substitute credential placeholders at the last moment before browser execution
|
|
@@ -535,47 +532,46 @@ class Runner
|
|
|
535
532
|
keys = substitute_credentials(keys) if contains_credential_placeholder?(keys)
|
|
536
533
|
|
|
537
534
|
response = send_to_node('type', { keys: keys }, eval_capture_data: eval_capture_data)
|
|
538
|
-
|
|
539
|
-
elements = response.dig('result', 'elements') || []
|
|
540
|
-
{ result: "Typed: #{display_keys}", screenshot_base64: screenshot_base64, elements: elements }
|
|
535
|
+
extract_result(response, "Typed: #{display_keys}")
|
|
541
536
|
|
|
542
537
|
when 'hotkey'
|
|
543
538
|
keys = action['keys']
|
|
544
539
|
response = send_to_node('hotkey', { keys: keys }, eval_capture_data: eval_capture_data)
|
|
545
|
-
|
|
546
|
-
elements = response.dig('result', 'elements') || []
|
|
547
|
-
{ result: "Hotkey: #{keys}", screenshot_base64: screenshot_base64, elements: elements }
|
|
540
|
+
extract_result(response, "Hotkey: #{keys}")
|
|
548
541
|
|
|
549
542
|
when 'wait'
|
|
550
543
|
response = send_to_node('wait', { ms: action['ms'] }, eval_capture_data: eval_capture_data)
|
|
551
|
-
|
|
552
|
-
elements = response.dig('result', 'elements') || []
|
|
553
|
-
{ result: "Waited #{action['ms']}ms", screenshot_base64: screenshot_base64, elements: elements }
|
|
544
|
+
extract_result(response, "Waited #{action['ms']}ms")
|
|
554
545
|
|
|
555
546
|
when 'scroll'
|
|
556
547
|
response = send_to_node('scroll', { direction: action['direction'] }, eval_capture_data: eval_capture_data)
|
|
557
|
-
|
|
558
|
-
elements = response.dig('result', 'elements') || []
|
|
559
|
-
{ result: "Scrolled #{action['direction']}", screenshot_base64: screenshot_base64, elements: elements }
|
|
548
|
+
extract_result(response, "Scrolled #{action['direction']}")
|
|
560
549
|
|
|
561
550
|
when 'accept_dialog'
|
|
562
551
|
value = action['value'] # Optional, for prompt dialogs
|
|
563
552
|
response = send_to_node('accept_dialog', { value: value }, eval_capture_data: eval_capture_data)
|
|
564
|
-
|
|
565
|
-
elements = response.dig('result', 'elements') || []
|
|
566
|
-
{ result: "Accepted dialog#{value ? " with value '#{value}'" : ''}", screenshot_base64: screenshot_base64, elements: elements }
|
|
553
|
+
extract_result(response, "Accepted dialog#{value ? " with value '#{value}'" : ''}")
|
|
567
554
|
|
|
568
555
|
when 'dismiss_dialog'
|
|
569
556
|
response = send_to_node('dismiss_dialog', {}, eval_capture_data: eval_capture_data)
|
|
570
|
-
|
|
571
|
-
elements = response.dig('result', 'elements') || []
|
|
572
|
-
{ result: "Dismissed dialog", screenshot_base64: screenshot_base64, elements: elements }
|
|
557
|
+
extract_result(response, "Dismissed dialog")
|
|
573
558
|
|
|
574
559
|
else
|
|
575
560
|
{ result: "Unknown action: #{action['action']}", screenshot_base64: nil, elements: nil }
|
|
576
561
|
end
|
|
577
562
|
end
|
|
578
563
|
|
|
564
|
+
def extract_result(response, description)
|
|
565
|
+
r = response['result'] || {}
|
|
566
|
+
{
|
|
567
|
+
result: description,
|
|
568
|
+
screenshot_base64: r['screenshot_base64'],
|
|
569
|
+
elements: r['elements'] || [],
|
|
570
|
+
page_url: r['page_url'],
|
|
571
|
+
duration_ms: r['duration_ms']
|
|
572
|
+
}
|
|
573
|
+
end
|
|
574
|
+
|
|
579
575
|
def build_elements_by_id(elements)
|
|
580
576
|
return {} unless elements
|
|
581
577
|
|
package/lib/step_client.rb
CHANGED
|
@@ -48,7 +48,7 @@ class StepClient
|
|
|
48
48
|
# Submit a step to the server
|
|
49
49
|
# Returns: { action: Hash, step_number: Integer, continue: Boolean }
|
|
50
50
|
def submit_step(scenario_id:, screenshot_base64:, elements:, previous_action: nil, action_result: nil,
|
|
51
|
-
pre_scenario_for_id: nil, execution_order: 0)
|
|
51
|
+
browser_result: nil, pre_scenario_for_id: nil, execution_order: 0)
|
|
52
52
|
body = {
|
|
53
53
|
scenario_id: scenario_id,
|
|
54
54
|
screenshot_base64: screenshot_base64,
|
|
@@ -58,6 +58,7 @@ class StepClient
|
|
|
58
58
|
|
|
59
59
|
body[:previous_action] = previous_action if previous_action
|
|
60
60
|
body[:action_result] = action_result if action_result
|
|
61
|
+
body[:browser_result] = browser_result if browser_result
|
|
61
62
|
body[:pre_scenario_for_id] = pre_scenario_for_id if pre_scenario_for_id
|
|
62
63
|
|
|
63
64
|
response = post("/api/runs/#{@server_run_id}/step", body)
|