@specsage/cli 0.1.2 → 0.1.5

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
@@ -93,21 +93,29 @@ class SpecSageCLI
93
93
  publisher = ResultsUploader.new(api_key: api_key)
94
94
 
95
95
  begin
96
- response = publisher.fetch_ci_scenarios(website)
96
+ scenarios_response = publisher.fetch_ci_scenarios(website)
97
+ scenarios = scenarios_response['scenarios']
97
98
  rescue ResultsUploader::UploadError => e
98
- puts "Error: #{e.message}"
99
+ puts "Error fetching scenarios: #{e.message}"
99
100
  exit 1
100
101
  end
101
102
 
102
- server_run_id = response['server_run_id']
103
- scenarios = response['scenarios']
104
-
105
- puts "Server run ID: #{server_run_id}"
106
103
  puts "Scenarios: #{scenarios.length}"
107
104
  scenarios.each { |s| puts " - #{s['name']}" }
108
105
  puts ""
109
106
 
110
- verdicts = []
107
+ begin
108
+ run_response = publisher.create_ci_run(website)
109
+ server_run_id = run_response['server_run_id']
110
+ rescue ResultsUploader::UploadError => e
111
+ puts "Error creating run: #{e.message}"
112
+ exit 1
113
+ end
114
+
115
+ puts "Server run ID: #{server_run_id}"
116
+ puts ""
117
+
118
+ results = []
111
119
 
112
120
  scenarios.each do |scenario|
113
121
  # Override base_url with CI_APP_URL
@@ -122,7 +130,7 @@ class SpecSageCLI
122
130
  )
123
131
 
124
132
  verdict = runner.run
125
- verdicts << verdict
133
+ results << { scenario: scenario, verdict: verdict }
126
134
  puts "[#{scenario['name']}] Verdict: #{verdict}"
127
135
  end
128
136
 
@@ -138,6 +146,8 @@ class SpecSageCLI
138
146
  puts "SpecSage CI Run Complete"
139
147
  puts "=" * 50
140
148
 
149
+ verdicts = results.map { |r| r[:verdict] }
150
+
141
151
  # Overall verdict: ERROR > FAIL > PASS
142
152
  overall = if verdicts.include?('ERROR')
143
153
  'ERROR'
@@ -150,6 +160,19 @@ class SpecSageCLI
150
160
  end
151
161
 
152
162
  puts "Overall Verdict: #{overall}"
163
+
164
+ # Print links to failed scenarios
165
+ failed_results = results.select { |r| r[:verdict] != 'PASS' }
166
+ if failed_results.any?
167
+ puts ""
168
+ puts "Failed scenarios:"
169
+ failed_results.each do |result|
170
+ scenario_id = result[:scenario]['id']
171
+ url = "https://app.specsage.com/runs/#{server_run_id}/scenarios/#{scenario_id}"
172
+ puts " - #{result[:scenario]['name']}: #{url}"
173
+ end
174
+ end
175
+
153
176
  puts ""
154
177
 
155
178
  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.2",
3
+ "version": "0.1.5",
4
4
  "description": "SpecSage CLI - AI-powered end-to-end testing automation (Node wrapper for Ruby CLI)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -29,5 +29,8 @@
29
29
  },
30
30
  "engines": {
31
31
  "node": ">=18.0.0"
32
+ },
33
+ "dependencies": {
34
+ "playwright": "^1.57.0"
32
35
  }
33
36
  }