onlyoffice_testrail_wrapper 0.1.0

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.
Files changed (28) hide show
  1. checksums.yaml +7 -0
  2. data/lib/onlyoffice_testrail_wrapper.rb +10 -0
  3. data/lib/onlyoffice_testrail_wrapper/helpers/hash_helper.rb +21 -0
  4. data/lib/onlyoffice_testrail_wrapper/helpers/rspec_helper.rb +24 -0
  5. data/lib/onlyoffice_testrail_wrapper/helpers/ruby_helper.rb +10 -0
  6. data/lib/onlyoffice_testrail_wrapper/helpers/string_helper.rb +12 -0
  7. data/lib/onlyoffice_testrail_wrapper/helpers/system_helper.rb +17 -0
  8. data/lib/onlyoffice_testrail_wrapper/mock/rspec_example_mock.rb +40 -0
  9. data/lib/onlyoffice_testrail_wrapper/name.rb +9 -0
  10. data/lib/onlyoffice_testrail_wrapper/rspec_extension.rb +14 -0
  11. data/lib/onlyoffice_testrail_wrapper/testrail.rb +187 -0
  12. data/lib/onlyoffice_testrail_wrapper/testrail_case.rb +67 -0
  13. data/lib/onlyoffice_testrail_wrapper/testrail_helper.rb +173 -0
  14. data/lib/onlyoffice_testrail_wrapper/testrail_helper/testrail_helper_rspec_metadata.rb +55 -0
  15. data/lib/onlyoffice_testrail_wrapper/testrail_helper/testrail_status_helper.rb +18 -0
  16. data/lib/onlyoffice_testrail_wrapper/testrail_milestone.rb +23 -0
  17. data/lib/onlyoffice_testrail_wrapper/testrail_plan.rb +92 -0
  18. data/lib/onlyoffice_testrail_wrapper/testrail_plan_entry.rb +16 -0
  19. data/lib/onlyoffice_testrail_wrapper/testrail_project.rb +227 -0
  20. data/lib/onlyoffice_testrail_wrapper/testrail_project/testrail_project_plan_helper.rb +65 -0
  21. data/lib/onlyoffice_testrail_wrapper/testrail_result.rb +47 -0
  22. data/lib/onlyoffice_testrail_wrapper/testrail_run.rb +147 -0
  23. data/lib/onlyoffice_testrail_wrapper/testrail_section.rb +109 -0
  24. data/lib/onlyoffice_testrail_wrapper/testrail_suite.rb +113 -0
  25. data/lib/onlyoffice_testrail_wrapper/testrail_test.rb +40 -0
  26. data/lib/onlyoffice_testrail_wrapper/testrail_tools/testrail_tools.rb +119 -0
  27. data/lib/onlyoffice_testrail_wrapper/version.rb +7 -0
  28. metadata +237 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c7cdb9209303106828ac8d2628bdfbd6243b0b66cbf9e57f8d1c3d506a29d0af
4
+ data.tar.gz: 54ad089da3f905190dc4b33784fbfc665faa725d865f0b28d77f034e4766b08e
5
+ SHA512:
6
+ metadata.gz: 86813255438a058617f52e431bd1465fe1a2aba8397dc62cd41efc51fc270c22c271a3c0e6a8c59645540896b8842eab77ce53a3614048f7d7f4da9016615ce1
7
+ data.tar.gz: e198cc8aa5f2b5c537ee36ff4e30c03ebb262a0485f7852d12f4ef333ce3f751e9046df74a1a842221f9e5b17358afc55ef2ea73f92d64099dbdf368e8655072
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'onlyoffice_logger_helper'
4
+ require_relative 'onlyoffice_testrail_wrapper/rspec_extension'
5
+ require_relative 'onlyoffice_testrail_wrapper/testrail_helper'
6
+ require_relative 'onlyoffice_testrail_wrapper/mock/rspec_example_mock'
7
+ require_relative 'onlyoffice_testrail_wrapper/helpers/hash_helper'
8
+ require_relative 'onlyoffice_testrail_wrapper/helpers/rspec_helper'
9
+ require_relative 'onlyoffice_testrail_wrapper/helpers/string_helper'
10
+ require_relative 'onlyoffice_testrail_wrapper/testrail_tools/testrail_tools'
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeTestrailWrapper
4
+ class HashHelper
5
+ class << self
6
+ def get_hash_from_array_with_two_parameters(array, key_parameter, value_parameter)
7
+ raise 'First argument must be Array!' unless array.is_a?(Array)
8
+
9
+ result_hash = {}
10
+ array.reverse_each { |element| result_hash[element[key_parameter]] = element[value_parameter] }
11
+ result_hash
12
+ end
13
+
14
+ def parse_to_class_variable(hash, class_name)
15
+ object = class_name.new
16
+ hash.each { |key, value| object.instance_variable_set("@#{key}", value) }
17
+ object
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeTestrailWrapper
4
+ # Methods to some rspec methods
5
+ module RspecHelper
6
+ # This method is based on
7
+ # https://github.com/rspec/rspec-core/blob/v3.3.0/lib/rspec/core/formatters/exception_presenter.rb#L130
8
+ # It extracted exact line of code from failed exception
9
+ # @param [RSpec::Core::Example] example
10
+ # @return [String] line value
11
+ def self.find_failed_line(example)
12
+ example_path = example.metadata[:absolute_file_path].downcase
13
+ dirty_line = example.exception.backtrace.find do |line|
14
+ next unless (line_path = line[/(.+?):(\d+)(|:\d+)/, 1])
15
+
16
+ File.expand_path(line_path).casecmp(example_path).zero?
17
+ end
18
+ line_number = dirty_line[/:\d*:/].delete(':').to_i
19
+ OnlyofficeFileHelper::FileHelper.read_array_from_file(example.metadata[:absolute_file_path])[line_number - 1]
20
+ rescue StandardError => e
21
+ "Cannot find failed line because of exception: #{e}"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeTestrailWrapper
4
+ # Methods to work with ruby
5
+ module RubyHelper
6
+ def debug?
7
+ ENV['RUBYLIB'].to_s.include?('ruby-debug')
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeTestrailWrapper
4
+ class StringHelper
5
+ class << self
6
+ def warnstrip!(string)
7
+ warn "Beginning or end of string has spaces! In: #{string}" unless string == string.strip
8
+ string.strip
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'socket'
4
+
5
+ module OnlyofficeTestrailWrapper
6
+ # Stuff for working with OS
7
+ class SystemHelper
8
+ class << self
9
+ # @return [String] name of current host
10
+ def hostname
11
+ name = Socket.gethostname
12
+ OnlyofficeLoggerHelper.log("hostname is: #{name}")
13
+ name
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeTestrailWrapper
4
+ # Mock Rspec example exception
5
+ class RspecExceptionMock
6
+ attr_accessor :backtrace
7
+
8
+ def initialize
9
+ @backtrace = %w[TestBackTraceLine1 TestBackTraceLine2]
10
+ end
11
+ end
12
+
13
+ # Class for mocking rspec result metadata
14
+ class RspecExceptionResultMock
15
+ attr_accessor :started_at
16
+ end
17
+
18
+ # Mock Rspec example
19
+ class RspecExampleMock
20
+ # @return [Object] object exception
21
+ attr_accessor :exception
22
+ # @return [Object] backtrace object
23
+ attr_accessor :backtrace
24
+ # @return [Hash] metadata
25
+ attr_accessor :metadata
26
+ # @return [True, False] is test pending
27
+ attr_accessor :pending
28
+ # @return [String] description of spec
29
+ attr_accessor :description
30
+
31
+ def initialize(description: 'MockDescription',
32
+ exception: RspecExceptionMock.new)
33
+ @exception = exception
34
+ @metadata = { execution_result: RspecExceptionResultMock.new }
35
+ @pending = false
36
+ @description = description
37
+ @section = ''
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeTestrailWrapper
4
+ # Module for storing gem name
5
+ module Name
6
+ # @return [String] gem name
7
+ STRING = 'onlyoffice_testrail_wrapper'
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Core
5
+ # Override for Rspec Example class
6
+ class Example
7
+ def add_custom_exception(comment)
8
+ e = Exception.exception(comment)
9
+ e.set_backtrace('')
10
+ @exception = e
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @author Roman.Zagudaev
4
+ # lib for working with http queries
5
+
6
+ require 'net/http'
7
+ require 'json'
8
+ require 'yaml'
9
+ require_relative 'testrail_project'
10
+
11
+ module OnlyofficeTestrailWrapper
12
+ # Main class for working with testrail
13
+ # dvd_copy = Project.init_project_by_name('AVS Disc Creator')
14
+ # compete_test_suit= dvd_copy.init_suite_by_name('Complete Test Suite')
15
+ # test_run_from_api = compete_test_suit.start_test_run('TestRunName', "Simple description")
16
+ # incompleted_test = test_run_from_api.get_incomplete_tests()
17
+ # while(incomplete_test.length > 0)
18
+ # current_test = incomplete_test.sample
19
+ # p current_test.title
20
+ # current_test.add_result(Testrail2::TEST_RESULT_OK, 'description','version')
21
+ # incomplete_test = test_run_from_api.get_incomplete_tests()
22
+ # end1
23
+ class Testrail2
24
+ # @return [String] address of testrail
25
+ @testrail_url = nil
26
+ # @return [String] login for admin user
27
+ @admin_user = nil
28
+ # @return [String] password for admin user
29
+ @admin_pass = nil
30
+
31
+ # @return [Hash] project information
32
+ attr_accessor :projects_names
33
+
34
+ def initialize
35
+ @projects_names = {}
36
+ end
37
+
38
+ class << self
39
+ attr_accessor :testrail_url
40
+ # Attribute to write admin_user
41
+ attr_writer :admin_user
42
+ # Attribute to write admin_pass
43
+ attr_writer :admin_pass
44
+
45
+ # @return [String] default config location
46
+ CONFIG_LOCATION = "#{Dir.home}/.gem-onlyoffice_testrail_wrapper/config.yml"
47
+
48
+ def read_keys
49
+ @testrail_url = ENV['TESTRAIL_URL']
50
+ @admin_user = ENV['TESTRAIL_USER']
51
+ @admin_pass = ENV['TESTRAIL_PASSWORD']
52
+ return unless @admin_user.nil? && @admin_pass.nil?
53
+
54
+ begin
55
+ yaml = YAML.load_file(CONFIG_LOCATION)
56
+ @testrail_url = yaml['url']
57
+ @admin_user = yaml['user']
58
+ @admin_pass = yaml['password']
59
+ rescue Errno::ENOENT
60
+ raise Errno::ENOENT, "No user of passwords found in #{CONFIG_LOCATION}. Please create correct config"
61
+ end
62
+ end
63
+
64
+ def admin_user
65
+ read_keys
66
+ @admin_user
67
+ end
68
+
69
+ def admin_pass
70
+ read_keys
71
+ @admin_pass
72
+ end
73
+
74
+ def get_testrail_address
75
+ read_keys unless testrail_url
76
+ testrail_url
77
+ end
78
+
79
+ # Perform http get on address
80
+ # @param [String] request_url to perform http get
81
+ # @return [Hash] Json with result data in hash form
82
+ def http_get(request_url)
83
+ uri = URI get_testrail_address + request_url
84
+ request = Net::HTTP::Get.new uri.request_uri
85
+ response = send_request(uri, request)
86
+ JSON.parse response.body
87
+ end
88
+
89
+ # Perform http post on address
90
+ # @param [String] request_url to perform http get
91
+ # @param [Hash] data_hash headers to add to post query
92
+ # @return [Hash] Json with result data in hash form
93
+ def http_post(request_url, data_hash)
94
+ uri = URI get_testrail_address + request_url
95
+ request = Net::HTTP::Post.new uri.request_uri
96
+ request.body = data_hash.to_json
97
+ response = send_request(uri, request)
98
+ return if response.body == ''
99
+
100
+ JSON.parse response.body
101
+ end
102
+ end
103
+
104
+ # region PROJECT
105
+
106
+ def project(name_or_id)
107
+ case name_or_id.class.to_s
108
+ when 'Fixnum'
109
+ get_project_by_id name_or_id
110
+ when 'String'
111
+ init_project_by_name name_or_id
112
+ else
113
+ raise 'Wrong argument. Must be name [String] or id [Integer]'
114
+ end
115
+ end
116
+
117
+ # Get all projects on testrail
118
+ # @return [Array, ProjectTestrail] array of projects
119
+ def get_projects
120
+ projects = Testrail2.http_get 'index.php?/api/v2/get_projects'
121
+ @projects_names = HashHelper.get_hash_from_array_with_two_parameters(projects, 'name', 'id') if @projects_names.empty?
122
+ projects
123
+ end
124
+
125
+ def create_new_project(name, announcement = '', show_announcement = true)
126
+ new_project = HashHelper.parse_to_class_variable(Testrail2.http_post('index.php?/api/v2/add_project', name: StringHelper.warnstrip!(name.to_s), announcement: announcement,
127
+ show_announcement: show_announcement), TestrailProject)
128
+ OnlyofficeLoggerHelper.log "Created new project: #{new_project.name}"
129
+ new_project.instance_variable_set('@testrail', self)
130
+ @projects_names[new_project.name] = new_project.id
131
+ new_project
132
+ end
133
+
134
+ # Initialize project by it's name
135
+ # @param [String] name name of project
136
+ # @return [TestrailProject] project with this name
137
+ def init_project_by_name(name)
138
+ found_project = get_project_by_name name
139
+ found_project.nil? ? create_new_project(name) : found_project
140
+ end
141
+
142
+ # Get all projects on testrail
143
+ # @return [Array, ProjectTestrail] array of projects
144
+ def get_project_by_id(id)
145
+ project = HashHelper.parse_to_class_variable(Testrail2.http_get("index.php?/api/v2/get_project/#{id}"), TestrailProject)
146
+ OnlyofficeLoggerHelper.log("Initialized project: #{project.name}")
147
+ project.instance_variable_set('@testrail', self)
148
+ project
149
+ end
150
+
151
+ def get_project_by_name(name)
152
+ get_projects if @projects_names.empty?
153
+ @projects_names[StringHelper.warnstrip!(name.to_s)].nil? ? nil : get_project_by_id(@projects_names[StringHelper.warnstrip!(name.to_s)])
154
+ end
155
+
156
+ # Check if Testrail connection is available
157
+ # @return [True, False] result of test connection
158
+ def available?
159
+ get_projects
160
+ true
161
+ rescue StandardError
162
+ false
163
+ end
164
+
165
+ # endregion
166
+
167
+ def self.send_request(uri, request)
168
+ request.basic_auth admin_user, admin_pass
169
+ request.delete 'content-type'
170
+ request.add_field 'content-type', 'application/json'
171
+ is_ssl = (uri.scheme == 'https')
172
+ Net::HTTP.start(uri.host, uri.port, use_ssl: is_ssl) do |http|
173
+ attempts = 0
174
+ begin
175
+ response = http.request(request)
176
+ rescue Timeout::Error
177
+ attempts += 1
178
+ retry if attempts < 3
179
+ raise 'Timeout error after 3 attempts'
180
+ rescue StandardError => e
181
+ raise e
182
+ end
183
+ return response
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnlyofficeTestrailWrapper
4
+ # @author Roman.Zagudaev
5
+ # Class for description of test case
6
+ class TestrailCase
7
+ # @return [Integer] Id of test case
8
+ attr_accessor :id
9
+ # @return [String] title of test case
10
+ attr_accessor :title
11
+ # @return [Integer] type id of test case
12
+ attr_accessor :type_id
13
+ # @return [Integer] priority id of test case
14
+ attr_accessor :priority_id
15
+ # @return [String] Steps of test case
16
+ attr_accessor :custom_steps
17
+ # @return [String] Estimated test time
18
+ attr_accessor :estimate
19
+
20
+ # Default constructor
21
+ # @param [String] title name of test case, default = nil
22
+ # @param [Integer] type_id type id of test case, default = 3
23
+ # @param [Integer] priority_id priority id of test case, default = 4
24
+ # @param [String] custom_steps Steps of test case
25
+ # @param [Integer] id Id of test case
26
+ # @return [TestCaseTestrail] new test case
27
+ def initialize(title = nil, type_id = 3, priority_id = 4, custom_steps = nil, id = nil)
28
+ @id = id
29
+ @title = title
30
+ @type_id = type_id
31
+ @priority_id = priority_id
32
+ @custom_steps = custom_steps
33
+ end
34
+
35
+ def update(title = @title, type_id = @type_id, priority_id = @priority_id, custom_steps = @custom_steps)
36
+ @section.cases_names.delete @title
37
+ @section.cases_names[StringHelper.warnstrip!(title.to_s)] = @id
38
+ HashHelper.parse_to_class_variable(Testrail2.http_post("index.php?/api/v2/update_case/#{@id}", title: title, type_id: type_id,
39
+ priority_id: priority_id, custom_steps: custom_steps), TestrailCase)
40
+ end
41
+
42
+ def delete
43
+ @section.cases_names.delete @title
44
+ OnlyofficeLoggerHelper.log "Deleted test case: #{@title}"
45
+ Testrail2.http_post "index.php?/api/v2/delete_case/#{@id}", {}
46
+ end
47
+
48
+ def get_results(run_id)
49
+ case_results = Testrail2.http_get "index.php?/api/v2/get_results_for_case/#{run_id}/#{@id}"
50
+ case_results.each_with_index { |test_case, index| case_results[index] = HashHelper.parse_to_class_variable(test_case, TestrailResult) }
51
+ case_results
52
+ end
53
+
54
+ def add_result(run_id, result, comment = '', custom_fields = {}, version = '')
55
+ response = HashHelper.parse_to_class_variable(Testrail2.http_post("index.php?/api/v2/add_result_for_case/#{run_id}/#{@id}", { status_id: TestrailResult::RESULT_STATUSES[result],
56
+ comment: comment, version: version }.merge(custom_fields)), TestrailResult)
57
+ OnlyofficeLoggerHelper.log "Set test case result: #{result}. URL: #{Testrail2.get_testrail_address}index.php?/tests/view/#{response.test_id}", output_colors[result]
58
+ response
59
+ end
60
+
61
+ private
62
+
63
+ def output_colors
64
+ { failed: 45, pending: 43, passed: 42, passed_2: 46, aborted: 41, blocked: 44 }
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,173 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'onlyoffice_bugzilla_helper'
4
+ require_relative 'testrail_helper/testrail_helper_rspec_metadata'
5
+ require_relative 'testrail_helper/testrail_status_helper'
6
+ require_relative 'testrail'
7
+ require_relative 'helpers/ruby_helper'
8
+ require_relative 'helpers/system_helper'
9
+
10
+ module OnlyofficeTestrailWrapper
11
+ # Class with help methods with testrail
12
+ class TestrailHelper
13
+ include RubyHelper
14
+ include TestrailHelperRspecMetadata
15
+ include TestrailStatusHelper
16
+ attr_reader :project, :plan, :suite, :run
17
+ attr_accessor :add_all_suites, :ignore_parameters, :suites_to_add, :search_plan_by_substring, :in_debug, :version
18
+
19
+ def initialize(project_name, suite_name = nil, plan_name = nil, run_name = nil)
20
+ @in_debug = debug?
21
+ begin
22
+ @bugzilla_helper = OnlyofficeBugzillaHelper::BugzillaHelper.new
23
+ rescue Errno::ENOENT
24
+ @bugzilla_helper = nil
25
+ end
26
+ if @in_debug
27
+ OnlyofficeLoggerHelper.log 'Do not initialize Testrail, because spec run in debug'
28
+ @run = TestrailRun.new
29
+ return
30
+ end
31
+ OnlyofficeLoggerHelper.log 'Begin initializing Testrail...'
32
+ @suites_to_add = []
33
+ @add_all_suites = true
34
+ @search_plan_by_substring = false
35
+ yield(self) if block_given?
36
+ @project = Testrail2.new.project project_name.to_s.dup
37
+ if plan_name
38
+ @plan = @project.get_plan_by_name(search_plan_by_substring ? get_plan_name_by_substring(plan_name.to_s) : plan_name.to_s)
39
+ @plan ||= @project.create_new_plan(plan_name, suites_to_add_hash(@add_all_suites ? all_suites_names : @suites_to_add))
40
+ end
41
+ return if suite_name.nil?
42
+
43
+ @suite = @project.suite suite_name.to_s
44
+ if @plan
45
+ init_run_in_plan(suite_name.to_s)
46
+ else
47
+ @run = @project.init_run_by_name(run_name ? run_name.to_s : suite_name.to_s, @suite.id)
48
+ end
49
+ raise "Plan '#{@plan.name}' is completed! Cannot add results. See #{@plan.url}" if !@plan.nil? && @plan.is_completed
50
+
51
+ OnlyofficeLoggerHelper.log 'Initializing complete!'
52
+ end
53
+
54
+ def add_cases_to_suite(cases, section_name = 'All Test Cases')
55
+ if @in_debug
56
+ OnlyofficeLoggerHelper.log 'Do not add test result, because spec run in debug '
57
+ return
58
+ end
59
+ OnlyofficeLoggerHelper.log "Begin scanning #{@suite.name} suite for new cases" unless cases.is_a?(Array)
60
+ section = @suite.section section_name.to_s
61
+ existing_cases = section.get_cases.map { |test_case| test_case['title'] }
62
+ cases.each { |case_name| section.create_new_case case_name.to_s unless existing_cases.include?(case_name) }
63
+ OnlyofficeLoggerHelper.log 'Suite scanning complete!'
64
+ @suite = @project.get_suite_by_id @suite.id
65
+ end
66
+
67
+ def add_result_to_test_case(example, comment = '', section_name = 'All Test Cases')
68
+ if @in_debug
69
+ OnlyofficeLoggerHelper.log 'Do not add test result, because spec run in debug '
70
+ return
71
+ end
72
+ exception = example.exception
73
+ custom_fields = init_custom_fields(example)
74
+ if @ignore_parameters && (ignored_hash = ignore_case?(example.metadata))
75
+ comment += "\nTest ignored by #{ignored_hash}"
76
+ result = :blocked
77
+ elsif example.pending
78
+ result, comment, bug_id = parse_pending_comment(example.execution_result.pending_message)
79
+ if example.exception.to_s == 'Expected example to fail since it is pending, but it passed.'
80
+ result = :failed
81
+ comment = "Test passed! #{comment}"
82
+ end
83
+ custom_fields[:defects] = bug_id.to_s
84
+ example.add_custom_exception(comment) if result == :failed
85
+ result = :lpv if comment.downcase.include?('limited program version')
86
+ elsif exception.to_s.include?('got:') || exception.to_s.include?('expected:')
87
+ result = :failed
88
+ failed_line = RspecHelper.find_failed_line(example)
89
+ comment += "\n#{exception.to_s.gsub('got:', "got:\n").gsub('expected:', "expected:\n")}\nIn line:\n#{failed_line}"
90
+ elsif exception.to_s.include?('to return') || exception.to_s.include?('expected')
91
+ result = :failed
92
+ comment += "\n#{exception.to_s.gsub('to return ', "to return:\n").gsub(', got ', "\ngot:\n")}"
93
+ elsif exception.to_s.include?('Service Unavailable')
94
+ result = :service_unavailable
95
+ comment += "\n#{exception}"
96
+ elsif exception.to_s.include?('Limited program version')
97
+ result = :lpv
98
+ comment += "\n#{exception}"
99
+ elsif exception.nil?
100
+ result = if @last_case == example.description
101
+ :passed_2
102
+ elsif custom_fields.key?(:custom_js_error)
103
+ :js_error
104
+ else
105
+ :passed
106
+ end
107
+ comment += "\nOk"
108
+ else
109
+ result = :aborted
110
+ comment += "\n#{exception}"
111
+ custom_fields[:custom_autotest_error_line] = exception.backtrace.join("\n") unless exception.backtrace.nil?
112
+ end
113
+ @last_case = example.description
114
+ @suite.section(section_name).case(example.description).add_result @run.id, result, comment, custom_fields
115
+ end
116
+
117
+ def add_result_by_case_name(name, result, comment = 'ok', section_name = 'All Test Cases')
118
+ @suite.section(section_name).case(name.to_s).add_result(@run.id, result, comment)
119
+ end
120
+
121
+ def get_incomplete_tests
122
+ @run.get_tests.map { |test| test['title'] if test['status_id'] == 3 || test['status_id'] == 4 }.compact
123
+ end
124
+
125
+ # @param [Array] result. Example: [:retest, :passed]
126
+ def get_tests_by_result(result)
127
+ check_status_exist(result)
128
+ result = [result] unless result.is_a?(Array)
129
+ @run.get_tests.map { |test| test['title'] if result.include?(TestrailResult::RESULT_STATUSES.key(test['status_id'])) }.compact
130
+ end
131
+
132
+ def delete_plan(plan_name)
133
+ @project.plan(get_plan_name_by_substring(plan_name.to_s)).delete
134
+ end
135
+
136
+ def mark_rest_environment_dependencies(supported_test_list, status_to_mark = :lpv)
137
+ get_incomplete_tests.each do |current_test|
138
+ add_result_by_case_name(current_test, status_to_mark, 'Not supported on this test environment') unless supported_test_list.include?(current_test)
139
+ end
140
+ end
141
+
142
+ private
143
+
144
+ def init_run_in_plan(run_name)
145
+ @plan.entries.each { |entry| @run = entry.runs.first if entry.name == run_name }
146
+ @run = @plan.add_entry(run_name, @suite.id).runs.first if @run.nil?
147
+ OnlyofficeLoggerHelper.log("Initialized run: #{@run.name}")
148
+ end
149
+
150
+ def get_plan_name_by_substring(string)
151
+ @project.get_plans.each { |plan| return plan['name'] if plan['name'].include?(string) }
152
+ string
153
+ end
154
+
155
+ def all_suites_names
156
+ @suites ? (return @suites) : @suites = []
157
+ @project.get_suites
158
+ @project.suites_names.each_key { |key| @suites << key }
159
+ @suites.sort!
160
+ end
161
+
162
+ def ignore_case?(example_metadata)
163
+ raise 'Ignore parameters must be Hash!!' unless @ignore_parameters.instance_of?(Hash)
164
+
165
+ @ignore_parameters.each { |key, value| return { key => value } if example_metadata[key] == value }
166
+ false
167
+ end
168
+
169
+ def suites_to_add_hash(suites_names)
170
+ suites_names.map { |suite| all_suites_names.include?(suite) ? { 'suite_id' => @project.suites_names[suite] } : { 'suite_id' => @project.create_new_suite(suite).id } }
171
+ end
172
+ end
173
+ end