hiptest-publisher 0.13.2 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c3b168dc9c0b80b37eb6ecfda66e3c1febeac5e3
4
- data.tar.gz: d446c3ee48325ae4ae22bca977816951e1ef487e
3
+ metadata.gz: 6a3a011230146c49dd11289311b1adb4c1f3ec07
4
+ data.tar.gz: 5af587b772286fdd2dda10b763ba57f16064589e
5
5
  SHA512:
6
- metadata.gz: 78c58933a727d82d28223a4be77f2d4c270ba9b1f7b815303ab7769ebabcbfc03e5e6ff8055fc44b149f650fe49d3e5ded41f97edc56e355cceed225b3682272
7
- data.tar.gz: af43ccc77d54009d6429ad124a93ed7f02ba956118f9d0a60bd97d09665d3ad965ce6e78b0ecca780cb88c5756af1e5b65270549a167dacebd8a8c64cce19cf7
6
+ metadata.gz: e3c8541ccec13d9c02f1160dbc1bfd1d5a985e0c01821dbbd0847d922356d766bd3c7dab148788b9acd4b6d2080e1e2ad2dfba4954399cc11ae221bbc3e704a7
7
+ data.tar.gz: 48da00daa178db580278ff93c4c94bcd723903b7cb8e4b19fee23685335dc26c94b22d7d2580c85ac0c788bdaae0eafa5914e4eb02e3c834671354a21ada66dd
@@ -5,6 +5,7 @@ require 'yaml'
5
5
 
6
6
  require 'hiptest-publisher/formatters/reporter'
7
7
  require 'hiptest-publisher/cli_options_checker'
8
+ require 'hiptest-publisher/client'
8
9
  require 'hiptest-publisher/string'
9
10
  require 'hiptest-publisher/utils'
10
11
  require 'hiptest-publisher/options_parser'
@@ -24,12 +25,12 @@ module Hiptest
24
25
  def initialize(args, listeners: nil, exit_on_bad_arguments: true)
25
26
  @reporter = Reporter.new(listeners)
26
27
  @cli_options = OptionsParser.parse(args, reporter)
28
+ @client = Hiptest::Client.new(@cli_options, reporter)
27
29
  # pass false to prevent hiptest-publisher from exiting, useful when used embedded
28
30
  @exit_on_bad_arguments = exit_on_bad_arguments
29
31
  end
30
32
 
31
33
  def run
32
- puts "URL: #{make_url(@cli_options)}".white if @cli_options.verbose
33
34
  begin
34
35
  CliOptionsChecker.new(@cli_options, reporter).check!
35
36
  rescue CliOptionError => e
@@ -43,16 +44,12 @@ module Hiptest
43
44
  return
44
45
  end
45
46
 
46
- if push?(@cli_options)
47
+ if @cli_options.push?
47
48
  post_results
48
49
  return
49
50
  end
50
51
 
51
- if @cli_options.xml_file
52
- xml = IO.read(@cli_options.xml_file)
53
- else
54
- xml = fetch_xml_file
55
- end
52
+ xml = get_xml_file
56
53
  return if xml.nil?
57
54
 
58
55
  @project = get_project(xml)
@@ -70,17 +67,32 @@ module Hiptest
70
67
  export
71
68
  end
72
69
 
70
+ def get_xml_file
71
+ if @cli_options.xml_file
72
+ IO.read(@cli_options.xml_file)
73
+ else
74
+ fetch_xml_file
75
+ end
76
+ end
77
+
73
78
  def fetch_xml_file
74
- with_status_message "Fetching data from Hiptest" do
75
- fetch_project_export(@cli_options)
79
+ reporter.with_status_message "Fetching data from Hiptest" do
80
+ @client.fetch_project_export
81
+ end
82
+ rescue ClientError => err
83
+ # This should not be an error that needs reporting to an exception monitoring app
84
+ puts err.message.yellow
85
+ if @exit_on_bad_arguments == false # means we are embedded in hiptest-publisher
86
+ raise
76
87
  end
77
88
  rescue Exception => err
78
- puts "Unable to open the file, please check that the token is correct".red
89
+ puts ("An error has occured, sorry for the inconvenience.\n" +
90
+ "Try running the command again with --verbose for detailed output").red
79
91
  reporter.dump_error(err)
80
92
  end
81
93
 
82
94
  def get_project(xml)
83
- with_status_message "Extracting data" do
95
+ reporter.with_status_message "Extracting data" do
84
96
  parser = Hiptest::XMLParser.new(xml, reporter)
85
97
  return parser.build_project
86
98
  end
@@ -89,7 +101,7 @@ module Hiptest
89
101
  end
90
102
 
91
103
  def write_to_file(path, message)
92
- with_status_message "#{message}: #{path}" do
104
+ reporter.with_status_message "#{message}: #{path}" do
93
105
  mkdirs_for(path)
94
106
  File.open(path, 'w') do |file|
95
107
  file.write(yield)
@@ -137,7 +149,7 @@ module Hiptest
137
149
 
138
150
  def show_actionwords_diff
139
151
  old = nil
140
- with_status_message "Loading previous definition" do
152
+ reporter.with_status_message "Loading previous definition" do
141
153
  old = YAML.load_file("#{@cli_options.output_directory}/actionwords_signature.yaml")
142
154
  end
143
155
 
@@ -239,7 +251,7 @@ module Hiptest
239
251
  def export
240
252
  return if @project.nil?
241
253
 
242
- with_status_message "Analyzing data" do
254
+ reporter.with_status_message "Analyzing data" do
243
255
  @language_config = LanguageConfigParser.new(@cli_options)
244
256
  Hiptest::Nodes::ParentAdder.add(@project)
245
257
  Hiptest::Nodes::ParameterTypeAdder.add(@project)
@@ -273,11 +285,11 @@ module Hiptest
273
285
 
274
286
  def post_results
275
287
  response = nil
276
- with_status_message "Posting #{@cli_options.push} to #{@cli_options.site}" do
277
- response = push_results(@cli_options)
288
+ reporter.with_status_message "Posting #{@cli_options.push} to #{@cli_options.site}" do
289
+ response = @client.push_results
278
290
  end
279
291
  passed_count = JSON.parse(response.body)['test_import'].size
280
- with_status_message "#{pluralize(passed_count, "test")} imported" do
292
+ reporter.with_status_message "#{pluralize(passed_count, "test")} imported" do
281
293
  if @cli_options.verbose
282
294
  JSON.parse(response.body)['test_import'].each do |imported_test|
283
295
  puts " Test '#{imported_test['name']}' imported"
@@ -22,7 +22,7 @@ module Hiptest
22
22
 
23
23
  check_secret_token
24
24
 
25
- if push?(cli_options)
25
+ if cli_options.push?
26
26
  check_push_file
27
27
  else
28
28
  check_output_directory
@@ -0,0 +1,115 @@
1
+ require 'json'
2
+ require 'net/http'
3
+ require 'uri'
4
+
5
+ require_relative 'formatters/reporter'
6
+
7
+ module Hiptest
8
+
9
+ class ClientError < StandardError
10
+ end
11
+
12
+ class Client
13
+ attr_reader :cli_options
14
+
15
+ def initialize(cli_options, reporter = nil)
16
+ @cli_options = cli_options
17
+ @reporter = reporter || NullReporter.new
18
+ end
19
+
20
+ def url
21
+ if cli_options.push?
22
+ "#{cli_options.site}/import_test_results/#{cli_options.token}/#{cli_options.push_format}"
23
+ elsif test_run_id
24
+ "#{base_publication_path}/test_run/#{test_run_id}"
25
+ else
26
+ "#{base_publication_path}/#{cli_options.leafless_export ? 'leafless_tests' : 'project'}"
27
+ end
28
+ end
29
+
30
+ def fetch_project_export
31
+ response = send_get_request(url)
32
+ response.body
33
+ end
34
+
35
+ def available_test_runs
36
+ @available_test_runs ||= begin
37
+ response = send_get_request("#{base_publication_path}/test_runs")
38
+ json_response = JSON.parse(response.body)
39
+ json_response["test_runs"]
40
+ end
41
+ end
42
+
43
+ def push_results
44
+ # Code from: https://github.com/nicksieger/multipart-post
45
+ uploaded = {}
46
+ Dir.glob(cli_options.push.gsub('\\', '/')).each_with_index do |filename, index|
47
+ uploaded["file-#{filename.normalize}"] = UploadIO.new(File.new(filename), "text", filename)
48
+ end
49
+
50
+ uri = URI.parse(url)
51
+ send_request(Net::HTTP::Post::Multipart.new(uri, uploaded))
52
+ end
53
+
54
+ private
55
+
56
+ def test_run_id
57
+ return unless cli_options.test_run_id? || cli_options.test_run_name?
58
+
59
+ if cli_options.test_run_id?
60
+ key = "id"
61
+ searched_value = cli_options.test_run_id
62
+ elsif cli_options.test_run_name?
63
+ key = "name"
64
+ searched_value = cli_options.test_run_name
65
+ end
66
+
67
+ matching_test_run = available_test_runs.find { |test_run| test_run[key] == searched_value }
68
+ if matching_test_run.nil?
69
+ raise ClientError, no_matching_test_runs_error_message
70
+ end
71
+ matching_test_run["id"]
72
+ end
73
+
74
+ def no_matching_test_runs_error_message
75
+ if available_test_runs.empty?
76
+ "No matching test run found: this project does not have any test runs."
77
+ else
78
+ "No matching test run found. Available test runs for this project are:\n" +
79
+ columnize_test_runs(available_test_runs)
80
+ end
81
+ end
82
+
83
+ def columnize_test_runs(test_runs)
84
+ lines = []
85
+ lines << ["ID", "Name"]
86
+ lines << ["--", "----"]
87
+ lines += test_runs.map { |tr| [tr["id"].to_s, tr["name"]] }
88
+ first_column_width = lines.map { |line| line[0].length }.max
89
+ lines.map! { |line| " #{line[0].ljust(first_column_width)} #{line[1]}" }
90
+ lines.join("\n")
91
+ end
92
+
93
+ def base_publication_path
94
+ "#{cli_options.site}/publication/#{cli_options.token}"
95
+ end
96
+
97
+ def send_get_request(url)
98
+ uri = URI.parse(url)
99
+ response = send_request(Net::HTTP::Get.new(uri))
100
+ if response.code_type == Net::HTTPNotFound
101
+ raise ClientError, "No project found with this secret token."
102
+ end
103
+ response
104
+ end
105
+
106
+ def send_request(request)
107
+ request["User-Agent"] = "Ruby/hiptest-publisher"
108
+ use_ssl = request.uri.scheme == "https"
109
+ Net::HTTP.start(request.uri.hostname, request.uri.port, use_ssl: use_ssl, :verify_mode => OpenSSL::SSL::VERIFY_NONE) do |http|
110
+ @reporter.show_verbose_message("Request sent to: #{request.uri}")
111
+ http.request(request)
112
+ end
113
+ end
114
+ end
115
+ end
@@ -5,6 +5,8 @@ class ConsoleFormatter
5
5
 
6
6
  def initialize(verbose)
7
7
  @verbose = verbose
8
+ @immediate_verbose = true
9
+ @verbose_messages = []
8
10
  end
9
11
 
10
12
  def dump_error(error, message = nil)
@@ -23,4 +25,43 @@ class ConsoleFormatter
23
25
  puts message.yellow
24
26
  options.each { |k, v| puts " - #{k}: #{v.inspect}" }
25
27
  end
28
+
29
+ def show_verbose_message(message)
30
+ return unless verbose
31
+ if @immediate_verbose
32
+ STDOUT.print "#{message}\n"
33
+ else
34
+ @verbose_messages << message
35
+ end
36
+ end
37
+
38
+ def show_status_message(message, status=nil)
39
+ status_icon = " "
40
+ output = STDOUT
41
+
42
+ if status == :success
43
+ status_icon = "v".green
44
+ elsif status == :failure
45
+ status_icon = "x".red
46
+ output = STDERR
47
+ end
48
+ if status
49
+ @immediate_verbose = true
50
+ cursor_offset = ""
51
+ else
52
+ return unless $stdout.tty?
53
+ rows, columns = IO.console.winsize
54
+ return if columns == 0
55
+ @immediate_verbose = false
56
+ vertical_offset = (4 + message.length) / columns
57
+ cursor_offset = "\r\e[#{vertical_offset + 1}A"
58
+ end
59
+
60
+ output.print "[#{status_icon}] #{message}#{cursor_offset}\n"
61
+
62
+ if @immediate_verbose && !@verbose_messages.empty?
63
+ @verbose_messages.each { |message| show_verbose_message(message) }
64
+ @verbose_messages.clear
65
+ end
66
+ end
26
67
  end
@@ -17,6 +17,21 @@ class Reporter
17
17
  notify(:show_options, options, message)
18
18
  end
19
19
 
20
+ def show_verbose_message(message)
21
+ notify(:show_verbose_message, message)
22
+ end
23
+
24
+ def with_status_message(message, &blk)
25
+ notify(:show_status_message, message)
26
+ status = :success
27
+ yield
28
+ rescue
29
+ status = :failure
30
+ raise
31
+ ensure
32
+ notify(:show_status_message, message, status)
33
+ end
34
+
20
35
  def notify(message, *args)
21
36
  @listeners.each do |listener|
22
37
  listener.send(message, *args)
@@ -76,6 +76,18 @@ class CliOptions < OpenStruct
76
76
  actionwords_diff || aw_deleted || aw_created || aw_renamed || aw_signature_changed || aw_definition_changed
77
77
  end
78
78
 
79
+ def push?
80
+ option_present?(push)
81
+ end
82
+
83
+ def test_run_id?
84
+ option_present?(test_run_id)
85
+ end
86
+
87
+ def test_run_name?
88
+ option_present?(test_run_name)
89
+ end
90
+
79
91
  def language_framework
80
92
  if framework.empty?
81
93
  language
@@ -119,6 +131,12 @@ class CliOptions < OpenStruct
119
131
  return delta
120
132
  end
121
133
  end
134
+
135
+ private
136
+
137
+ def option_present?(value)
138
+ value && !value.empty?
139
+ end
122
140
  end
123
141
 
124
142
  class OptionsParser
@@ -150,7 +168,8 @@ class OptionsParser
150
168
  Option.new(nil, 'filename-pattern=PATTERN', nil, String, "Filename pattern (containing %s)", :filename_pattern),
151
169
  Option.new('c', 'config-file=PATH', nil, String, "Configuration file", :config),
152
170
  Option.new(nil, 'overriden-templates=PATH', '', String, "Folder for overriden templates", :overriden_templates),
153
- Option.new(nil, 'test-run-id=ID', '', String, "Export data from a test run", :test_run_id),
171
+ Option.new(nil, 'test-run-id=ID', '', String, "Export data from a test run identified by its id", :test_run_id),
172
+ Option.new(nil, 'test-run-name=NAME', '', String, "Export data from a test run identified by its name", :test_run_name),
154
173
  Option.new(nil, 'only=CATEGORIES', nil, String, "Restrict export to given file categories (--only=list to list them)", :only),
155
174
  Option.new('x', 'xml-file=PROJECT_XML', nil, String, "XML file to use instead of fetching it from Hiptest", :xml_file),
156
175
  Option.new(nil, 'tests-only', false, nil, "(deprecated) alias for --only=tests", :tests_only),
@@ -1,6 +1,5 @@
1
1
  require 'colorize'
2
2
  require 'io/console'
3
- require 'open-uri'
4
3
  require 'openssl'
5
4
  require 'net/http/post/multipart'
6
5
  require 'pathname'
@@ -35,79 +34,6 @@ def singularize(name)
35
34
  name.to_s.chomp("s")
36
35
  end
37
36
 
38
- def make_url(options)
39
- if push?(options)
40
- "#{options.site}/import_test_results/#{options.token}/#{options.push_format}"
41
- else
42
- base_url = "#{options.site}/publication/#{options.token}"
43
- if options.test_run_id.nil? || options.test_run_id.empty?
44
- "#{base_url}/#{options.leafless_export ? 'leafless_tests' : 'project'}"
45
- else
46
- "#{base_url}/test_run/#{options.test_run_id}"
47
- end
48
- end
49
- end
50
-
51
- def fetch_project_export(options)
52
- url = make_url(options)
53
-
54
- open(url, "User-Agent" => 'Ruby/hiptest-publisher', :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE)
55
- end
56
-
57
- def show_status_message(message, status=nil)
58
- status_icon = " "
59
- output = STDOUT
60
-
61
- if status == :success
62
- status_icon = "v".green
63
- elsif status == :failure
64
- status_icon = "x".red
65
- output = STDERR
66
- end
67
- if status
68
- cursor_offset = ""
69
- else
70
- return unless $stdout.tty?
71
- rows, columns = IO.console.winsize
72
- return if columns == 0
73
- vertical_offset = (4 + message.length) / columns
74
- cursor_offset = "\r\e[#{vertical_offset + 1}A"
75
- end
76
-
77
- output.print "[#{status_icon}] #{message}#{cursor_offset}\n"
78
- end
79
-
80
- def with_status_message(message, &blk)
81
- show_status_message message
82
- status = :success
83
- yield
84
- rescue
85
- status = :failure
86
- raise
87
- ensure
88
- show_status_message message, status
89
- end
90
-
91
- def push?(options)
92
- options.push && !options.push.empty?
93
- end
94
-
95
- def push_results(options)
96
- # Code from: https://github.com/nicksieger/multipart-post
97
- url = URI.parse(make_url(options))
98
- use_ssl = (url.scheme == 'https')
99
- uploaded = {}
100
-
101
- Dir.glob(options.push.gsub('\\', '/')).each_with_index do |filename, index|
102
- uploaded["file-#{filename.normalize}"] = UploadIO.new(File.new(filename), "text", filename)
103
- end
104
-
105
- req = Net::HTTP::Post::Multipart.new(url.path, uploaded)
106
- response = Net::HTTP.start(url.host, url.port, :use_ssl => use_ssl, :verify_mode => OpenSSL::SSL::VERIFY_NONE) do |http|
107
- http.request(req)
108
- end
109
- end
110
-
111
37
  def clean_path(path)
112
38
  Pathname.new(path).cleanpath.to_s
113
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hiptest-publisher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.2
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hiptest R&D
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-08 00:00:00.000000000 Z
11
+ date: 2016-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -261,6 +261,7 @@ files:
261
261
  - lib/hiptest-publisher/actionword_indexer.rb
262
262
  - lib/hiptest-publisher/call_arguments_adder.rb
263
263
  - lib/hiptest-publisher/cli_options_checker.rb
264
+ - lib/hiptest-publisher/client.rb
264
265
  - lib/hiptest-publisher/formatters/console_formatter.rb
265
266
  - lib/hiptest-publisher/formatters/reporter.rb
266
267
  - lib/hiptest-publisher/gherkin_adder.rb
@@ -595,7 +596,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
595
596
  version: '0'
596
597
  requirements: []
597
598
  rubyforge_project:
598
- rubygems_version: 2.4.8
599
+ rubygems_version: 2.6.4
599
600
  signing_key:
600
601
  specification_version: 4
601
602
  summary: Export your tests from Hiptest into executable tests.