@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 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
- response = publisher.fetch_ci_scenarios(website)
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
- verdicts = []
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
- verdicts << verdict
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
@@ -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 server_run_id and scenarios array
54
+ # Returns hash with version and scenarios array
55
55
  def fetch_ci_scenarios(website_identifier)
56
- get("/api/v1/ci/scenarios?website=#{website_identifier}")
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
- break if action['action'] == 'verdict'
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specsage/cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.7",
4
4
  "description": "SpecSage CLI - AI-powered end-to-end testing automation (Node wrapper for Ruby CLI)",
5
5
  "type": "module",
6
6
  "bin": {