@specsage/cli 0.1.4 → 0.1.7
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/cli.rb +34 -8
- package/lib/results_uploader.rb +10 -3
- package/lib/runner.rb +9 -1
- package/package.json +1 -1
package/lib/cli.rb
CHANGED
|
@@ -17,6 +17,8 @@ require 'runner'
|
|
|
17
17
|
require 'results_uploader'
|
|
18
18
|
|
|
19
19
|
class SpecSageCLI
|
|
20
|
+
VERSION = '0.1.6'
|
|
21
|
+
|
|
20
22
|
def initialize(args)
|
|
21
23
|
@args = args
|
|
22
24
|
@options = {
|
|
@@ -86,6 +88,7 @@ class SpecSageCLI
|
|
|
86
88
|
|
|
87
89
|
puts "SpecSage CI Mode"
|
|
88
90
|
puts "=" * 50
|
|
91
|
+
puts "Version: #{VERSION}"
|
|
89
92
|
puts "Website: #{website}"
|
|
90
93
|
puts "Base URL: #{base_url}"
|
|
91
94
|
puts ""
|
|
@@ -93,21 +96,29 @@ class SpecSageCLI
|
|
|
93
96
|
publisher = ResultsUploader.new(api_key: api_key)
|
|
94
97
|
|
|
95
98
|
begin
|
|
96
|
-
|
|
99
|
+
scenarios_response = publisher.fetch_ci_scenarios(website)
|
|
100
|
+
scenarios = scenarios_response['scenarios']
|
|
97
101
|
rescue ResultsUploader::UploadError => e
|
|
98
|
-
puts "Error: #{e.message}"
|
|
102
|
+
puts "Error fetching scenarios: #{e.message}"
|
|
99
103
|
exit 1
|
|
100
104
|
end
|
|
101
105
|
|
|
102
|
-
server_run_id = response['server_run_id']
|
|
103
|
-
scenarios = response['scenarios']
|
|
104
|
-
|
|
105
|
-
puts "Server run ID: #{server_run_id}"
|
|
106
106
|
puts "Scenarios: #{scenarios.length}"
|
|
107
107
|
scenarios.each { |s| puts " - #{s['name']}" }
|
|
108
108
|
puts ""
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
begin
|
|
111
|
+
run_response = publisher.create_ci_run(website)
|
|
112
|
+
server_run_id = run_response['server_run_id']
|
|
113
|
+
rescue ResultsUploader::UploadError => e
|
|
114
|
+
puts "Error creating run: #{e.message}"
|
|
115
|
+
exit 1
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
puts "Server run ID: #{server_run_id}"
|
|
119
|
+
puts ""
|
|
120
|
+
|
|
121
|
+
results = []
|
|
111
122
|
|
|
112
123
|
scenarios.each do |scenario|
|
|
113
124
|
# Override base_url with CI_APP_URL
|
|
@@ -122,7 +133,7 @@ class SpecSageCLI
|
|
|
122
133
|
)
|
|
123
134
|
|
|
124
135
|
verdict = runner.run
|
|
125
|
-
|
|
136
|
+
results << { scenario: scenario, verdict: verdict }
|
|
126
137
|
puts "[#{scenario['name']}] Verdict: #{verdict}"
|
|
127
138
|
end
|
|
128
139
|
|
|
@@ -138,6 +149,8 @@ class SpecSageCLI
|
|
|
138
149
|
puts "SpecSage CI Run Complete"
|
|
139
150
|
puts "=" * 50
|
|
140
151
|
|
|
152
|
+
verdicts = results.map { |r| r[:verdict] }
|
|
153
|
+
|
|
141
154
|
# Overall verdict: ERROR > FAIL > PASS
|
|
142
155
|
overall = if verdicts.include?('ERROR')
|
|
143
156
|
'ERROR'
|
|
@@ -150,6 +163,19 @@ class SpecSageCLI
|
|
|
150
163
|
end
|
|
151
164
|
|
|
152
165
|
puts "Overall Verdict: #{overall}"
|
|
166
|
+
|
|
167
|
+
# Print links to failed scenarios
|
|
168
|
+
failed_results = results.select { |r| r[:verdict] != 'PASS' }
|
|
169
|
+
if failed_results.any?
|
|
170
|
+
puts ""
|
|
171
|
+
puts "Failed scenarios:"
|
|
172
|
+
failed_results.each do |result|
|
|
173
|
+
scenario_id = result[:scenario]['id']
|
|
174
|
+
url = "https://app.specsage.com/runs/#{server_run_id}/scenarios/#{scenario_id}"
|
|
175
|
+
puts " - #{result[:scenario]['name']}: #{url}"
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
153
179
|
puts ""
|
|
154
180
|
|
|
155
181
|
case overall
|
package/lib/results_uploader.rb
CHANGED
|
@@ -51,15 +51,22 @@ class ResultsUploader
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
# Fetch CI scenarios - returns scenario definitions tagged "ci" for local execution
|
|
54
|
-
# Returns hash with
|
|
54
|
+
# Returns hash with version and scenarios array
|
|
55
55
|
def fetch_ci_scenarios(website_identifier)
|
|
56
|
-
get("/api/v1/ci/scenarios
|
|
56
|
+
get("/api/v1/ci/scenarios", website: website_identifier)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Create a CI run on the server
|
|
60
|
+
# Returns hash with server_run_id and base_url
|
|
61
|
+
def create_ci_run(website_identifier)
|
|
62
|
+
post("/api/v1/ci/runs", { website: website_identifier })
|
|
57
63
|
end
|
|
58
64
|
|
|
59
65
|
private
|
|
60
66
|
|
|
61
|
-
def get(path)
|
|
67
|
+
def get(path, params = {})
|
|
62
68
|
uri = URI.parse("#{@base_url}#{path}")
|
|
69
|
+
uri.query = URI.encode_www_form(params) unless params.empty?
|
|
63
70
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
64
71
|
http.use_ssl = uri.scheme == 'https'
|
|
65
72
|
http.open_timeout = 10
|
package/lib/runner.rb
CHANGED
|
@@ -60,6 +60,7 @@ class Runner
|
|
|
60
60
|
interactive_elements_by_id = build_elements_by_id(interactive_elements)
|
|
61
61
|
previous_action = nil
|
|
62
62
|
action_result = nil
|
|
63
|
+
final_verdict = 'ERROR' # Default to ERROR if no verdict received
|
|
63
64
|
|
|
64
65
|
loop do
|
|
65
66
|
# Get next action from server
|
|
@@ -94,7 +95,10 @@ class Runner
|
|
|
94
95
|
# Log action with element details
|
|
95
96
|
safe_puts " [Step #{step_result[:step_number]}] #{action['action']}: #{action.reject { |k, _| k == 'action' }.to_json}"
|
|
96
97
|
|
|
97
|
-
|
|
98
|
+
if action['action'] == 'verdict'
|
|
99
|
+
final_verdict = action['status'] || 'ERROR'
|
|
100
|
+
break
|
|
101
|
+
end
|
|
98
102
|
|
|
99
103
|
# Skip browser execution for meta actions
|
|
100
104
|
unless BROWSER_ACTIONS.include?(action['action'])
|
|
@@ -125,6 +129,7 @@ class Runner
|
|
|
125
129
|
if @max_steps && step_number >= @max_steps
|
|
126
130
|
log "Step limit exceeded (#{@max_steps})."
|
|
127
131
|
send_client_verdict_if_needed('ERROR', "Step limit exceeded (#{@max_steps}).")
|
|
132
|
+
final_verdict = 'ERROR'
|
|
128
133
|
break
|
|
129
134
|
end
|
|
130
135
|
|
|
@@ -135,16 +140,19 @@ class Runner
|
|
|
135
140
|
stop_node_process
|
|
136
141
|
upload_video
|
|
137
142
|
cleanup_temp_dir
|
|
143
|
+
final_verdict
|
|
138
144
|
rescue StepClient::StepError => e
|
|
139
145
|
send_client_verdict_if_needed('ERROR', "Server error: #{e.message}")
|
|
140
146
|
stop_node_process
|
|
141
147
|
upload_video
|
|
142
148
|
cleanup_temp_dir
|
|
149
|
+
'ERROR'
|
|
143
150
|
rescue StandardError => e
|
|
144
151
|
send_client_verdict_if_needed('ERROR', e.message)
|
|
145
152
|
stop_node_process
|
|
146
153
|
upload_video
|
|
147
154
|
cleanup_temp_dir
|
|
155
|
+
'ERROR'
|
|
148
156
|
end
|
|
149
157
|
|
|
150
158
|
private
|