onlyoffice_testrail_wrapper 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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