rspec_junit_formatter 0.6.0 → 0.7.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 903f156687c6fff260143332222e9950fca53b5306bcde7cf197c44f3af4acf7
4
- data.tar.gz: 1d2ffca113b3cd78b3230d66ed41268609ce38f06e50da6cd196af9073670500
3
+ metadata.gz: f8938b63b79c5d0cfd77464773645cca9a0c72b11c5d3f1fe7fc92d0279c4021
4
+ data.tar.gz: 9fc9a172d1292bb89a368e889f2f90165e47b087dd5c39fe7a154d9480ca3f61
5
5
  SHA512:
6
- metadata.gz: f8d32b7a3b5dec828fe29c714755b3698ad8a48b1cfc92185b6f53e5eb4a6ab47adae5cb74743cbc6b5814d0a5d61d15d49b632aadd5afdede74820628796687
7
- data.tar.gz: 76537f5a365796f1e062cbfde157f8f48c163b7973ae6a1faae533cbf4684bd3c29cd26d6cb344eac8c46c0ae950f854b48f21bbf2bd28bfbf2ebab6e12b639e
6
+ metadata.gz: e4c83896373201abf5ec66c1cc8dc858e44eb3def5546646e2ca72d36ea2dd70cb44d42b9db2d51d094daa46b3248fd4a189edced96f1db1a2319d4f38bdfff6
7
+ data.tar.gz: f3619e7aaef1751d2dc433c41e2c6608e77d31483e550fa8ce47ad95352f21c7052b10fa8b447b1f00d2a21b5d883be017939f120162fb5f635238088230aeca
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![Build results](https://github.com/sj26/rspec_junit_formatter/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/sj26/rspec_junit_formatter/actions/workflows/ci.yml?branch=main)
4
4
  [![Gem version](http://img.shields.io/gem/v/rspec_junit_formatter.svg)](https://rubygems.org/gems/rspec_junit_formatter)
5
5
 
6
- [RSpec][rspec] 2 & 3 results that your CI can read. [Jenkins][jenkins-junit], [Buildkite][buildkite-junit], [CircleCI][circleci-junit], [Gitlab][gitlab-junit], and probably more, too.
6
+ [RSpec][rspec] 3 results that your CI can read. [Jenkins][jenkins-junit], [Buildkite][buildkite-junit], [CircleCI][circleci-junit], [Gitlab][gitlab-junit], and probably more, too.
7
7
 
8
8
  [rspec]: http://rspec.info/
9
9
  [jenkins-junit]: https://jenkins.io/doc/pipeline/steps/junit/
@@ -13,6 +13,8 @@
13
13
 
14
14
  ## Usage
15
15
 
16
+ Requires Ruby >= 3.3 and RSpec >= 3.13, < 4. For older versions, see [legacy support](#supported-versions-and-legacy-upgrades).
17
+
16
18
  Install the gem:
17
19
 
18
20
  ```sh
@@ -33,7 +35,7 @@ You can use it in combination with other [formatters][rspec-formatters], too:
33
35
  rspec --format progress --format RspecJunitFormatter --out rspec.xml
34
36
  ```
35
37
 
36
- [rspec-formatters]: https://relishapp.com/rspec/rspec-core/v/3-6/docs/formatters
38
+ [rspec-formatters]: https://rspec.info/features/3-12/rspec-core/formatters/
37
39
 
38
40
  ### Using in your project with Bundler
39
41
 
@@ -42,7 +44,7 @@ Add it to your Gemfile if you're using [Bundler][bundler]. Put it in the same gr
42
44
  ```ruby
43
45
  group :test do
44
46
  gem "rspec"
45
- gem "rspec_junit_formatter"
47
+ gem "rspec_junit_formatter", require: false
46
48
  end
47
49
  ```
48
50
 
@@ -53,7 +55,7 @@ Put the same arguments as the commands above in [your `.rspec`][rspec-file]:
53
55
  --out rspec.xml
54
56
  ```
55
57
  [bundler]: https://bundler.io
56
- [rspec-file]: https://relishapp.com/rspec/rspec-core/v/3-6/docs/configuration/read-command-line-configuration-options-from-files
58
+ [rspec-file]: https://rspec.info/features/3-12/rspec-core/configuration/read-options-from-file/
57
59
 
58
60
  ### Parallel tests
59
61
 
@@ -90,23 +92,30 @@ RSpec.configure do |config|
90
92
  end
91
93
  ```
92
94
 
93
- Note that this example captures all output from every example all the time, potentially interfering with local debugging. You might like to restrict this to only on CI, or by using [rspec filters](https://relishapp.com/rspec/rspec-core/docs/hooks/filters).
95
+ Note that this example captures all output from every example all the time, potentially interfering with local debugging. You might like to restrict this to only on CI, or by using [rspec filters](https://rspec.info/features/3-12/rspec-core/hooks/filtering/).
94
96
 
95
97
  ## Caveats
96
98
 
97
99
  * XML can only represent a [limited subset of characters][xml-charsets] which excludes null bytes and most control characters. This gem will use character entities where possible and fall back to replacing invalid characters with Ruby-like escape codes otherwise. For example, the null byte becomes `\0`.
100
+ * When converting report text to UTF-8 for XML output, invalid byte sequences and characters with no UTF-8 conversion are replaced with `�` (U+FFFD REPLACEMENT CHARACTER). The formatter uses each string's declared encoding; it does not guess the encoding of binary data.
98
101
 
99
102
  [xml-charsets]: https://www.w3.org/TR/xml/#charsets
100
103
 
101
- ## Development
104
+ ## Supported versions and legacy upgrades
105
+
106
+ We support [maintained Ruby versions](https://www.ruby-lang.org/en/downloads/branches/), including security maintenance, and [the current stable RSpec series](https://rspec.info/blog/2024/11/introducing-the-monorepo/). Minor releases may raise the minimum versions when upstream support ends.
107
+
108
+ For Ruby < 3.3 or RSpec < 3.13, use [0.6.2](https://rubygems.org/gems/rspec_junit_formatter/versions/0.6.2), the final legacy release:
102
109
 
103
- Run the specs with `bundle exec rake`, which uses [Appraisal][appraisal] to run the specs against all supported versions of rspec.
110
+ ```ruby
111
+ gem "rspec_junit_formatter", "0.6.2", require: false
112
+ ```
104
113
 
105
- [appraisal]: https://github.com/thoughtbot/appraisal
114
+ Run `bundle update rspec_junit_formatter`, or install without Bundler using `gem install rspec_junit_formatter -v 0.6.2`. This release permits Ruby >= 2.3 and RSpec >= 2, < 4, except 2.12.0; see its [tested combinations](https://github.com/sj26/rspec_junit_formatter/blob/v0.6.2/README.md#tested-versus-permitted-versions).
106
115
 
107
- ## Releasing
116
+ ## Contributing
108
117
 
109
- Bump the gem version in the gemspec, and commit. Then `bundle exec rake build` to build a gem package, `bundle exec rake install` to install and test it locally, then `bundle exec rake release` to tag and push the commits and gem.
118
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development, testing and release instructions.
110
119
 
111
120
  ## License
112
121
 
@@ -46,12 +46,7 @@ private
46
46
  end
47
47
 
48
48
  def error_count
49
- # Introduced in rspec 3.6
50
- if @summary_notification.respond_to?(:errors_outside_of_examples_count)
51
- @summary_notification.errors_outside_of_examples_count
52
- else
53
- 0
54
- end
49
+ @summary_notification.errors_outside_of_examples_count
55
50
  end
56
51
 
57
52
  def result_of(notification)
@@ -88,7 +83,15 @@ private
88
83
  end
89
84
 
90
85
  def failure_for(notification)
91
- strip_diff_colors(notification.message_lines.join("\n")) << "\n" << notification.formatted_backtrace.join("\n")
86
+ exception = exception_for(notification)
87
+
88
+ details = if aggregate_failure?(exception)
89
+ strip_diff_colors(exception.message)
90
+ else
91
+ strip_diff_colors(notification.message_lines.join("\n")) << "\n" << notification.formatted_backtrace.join("\n")
92
+ end
93
+
94
+ details.gsub(/ +$/, '')
92
95
  end
93
96
 
94
97
  def exception_for(notification)
@@ -119,19 +122,8 @@ private
119
122
 
120
123
  # Completely gross hack for absolutely forcing off colorising for the
121
124
  # duration of a block.
122
- if RSpec.configuration.respond_to?(:color_mode=)
123
- def without_color(&block)
124
- swap_rspec_configuration(:color_mode, :off, &block)
125
- end
126
- elsif RSpec.configuration.respond_to?(:color=)
127
- def without_color(&block)
128
- swap_rspec_configuration(:color, false, &block)
129
- end
130
- else
131
- warn 'rspec_junit_formatter cannot prevent colorising due to an unexpected RSpec.configuration format'
132
- def without_color
133
- yield
134
- end
125
+ def without_color(&block)
126
+ swap_rspec_configuration(:color_mode, :off, &block)
135
127
  end
136
128
 
137
129
  def stdout_for(example_notification)
@@ -141,18 +133,11 @@ private
141
133
  def stderr_for(example_notification)
142
134
  example_notification.example.metadata[:stderr]
143
135
  end
144
- end
145
136
 
146
- # rspec-core 3.0.x forgot to mark this as a module function which causes:
147
- #
148
- # NoMethodError: undefined method `wrap' for RSpec::Core::Notifications::NullColorizer:Class
149
- # .../rspec-core-3.0.4/lib/rspec/core/notifications.rb:229:in `add_shared_group_line'
150
- # .../rspec-core-3.0.4/lib/rspec/core/notifications.rb:157:in `message_lines'
151
- #
152
- if defined?(RSpec::Core::Notifications::NullColorizer) && RSpec::Core::Notifications::NullColorizer.is_a?(Class) && !RSpec::Core::Notifications::NullColorizer.respond_to?(:wrap)
153
- RSpec::Core::Notifications::NullColorizer.class_eval do
154
- def self.wrap(*args)
155
- new.wrap(*args)
156
- end
137
+ def aggregate_failure?(exception)
138
+ # rspec-expectations is optional; the formatter only depends on rspec-core.
139
+ return false unless defined?(RSpec::Expectations::MultipleExpectationsNotMetError)
140
+
141
+ exception.is_a?(RSpec::Expectations::MultipleExpectationsNotMetError)
157
142
  end
158
143
  end
@@ -9,8 +9,6 @@ require "rspec/core/formatters/base_formatter"
9
9
  # Dumps rspec results as a JUnit XML file.
10
10
  # Based on XML schema: http://windyroad.org/dl/Open%20Source/JUnit.xsd
11
11
  class RSpecJUnitFormatter < RSpec::Core::Formatters::BaseFormatter
12
- # rspec 2 and 3 implements are in separate files.
13
-
14
12
  private
15
13
 
16
14
  def xml_dump
@@ -164,9 +162,13 @@ private
164
162
  ?>.freeze => "&gt;".freeze,
165
163
  ).freeze
166
164
 
165
+ def utf8(text)
166
+ text.to_s.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "\uFFFD")
167
+ end
168
+
167
169
  def escape(text)
168
170
  # Make sure it's utf-8, replace illegal characters with ruby-like escapes, and replace special and discouraged characters with entities
169
- text.to_s.encode(Encoding::UTF_8).gsub(ILLEGAL_REGEXP, ILLEGAL_REPLACEMENT).gsub(DISCOURAGED_REGEXP, DISCOURAGED_REPLACEMENTS)
171
+ utf8(text).gsub(ILLEGAL_REGEXP, ILLEGAL_REPLACEMENT).gsub(DISCOURAGED_REGEXP, DISCOURAGED_REPLACEMENTS)
170
172
  end
171
173
 
172
174
  STRIP_DIFF_COLORS_BLOCK_REGEXP = /^ ( [ ]* ) Diff: (?: \e\[ 0 m )? (?: \n \1 \e\[ \d+ (?: ; \d+ )* m .* )* /x
@@ -182,14 +184,12 @@ private
182
184
  # We also only want to target the diff hunks because the failure message
183
185
  # itself might legitimately contain ansi escape codes.
184
186
  #
185
- string.sub(STRIP_DIFF_COLORS_BLOCK_REGEXP) { |match| match.gsub(STRIP_DIFF_COLORS_CODES_REGEXP, "".freeze) }
187
+ # Transcode before matching: the original message may be invalid or use an
188
+ # encoding incompatible with the ASCII regexp. Leave XML escaping until later.
189
+ utf8(string).sub(STRIP_DIFF_COLORS_BLOCK_REGEXP) { |match| match.gsub(STRIP_DIFF_COLORS_CODES_REGEXP, "".freeze) }
186
190
  end
187
191
  end
188
192
 
189
193
  RspecJunitFormatter = RSpecJUnitFormatter
190
194
 
191
- if Gem::Version.new(RSpec::Core::Version::STRING) >= Gem::Version.new("3")
192
- require "rspec_junit_formatter/rspec3"
193
- else
194
- require "rspec_junit_formatter/rspec2"
195
- end
195
+ require "rspec_junit_formatter/rspec3"
metadata CHANGED
@@ -1,35 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec_junit_formatter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Cochran
8
- autorequire:
9
8
  bindir: bin
10
- cert_chain:
11
- - |
12
- -----BEGIN CERTIFICATE-----
13
- MIIDXDCCAkSgAwIBAgIBATANBgkqhkiG9w0BAQsFADA6MQ0wCwYDVQQDDARzajI2
14
- MRQwEgYKCZImiZPyLGQBGRYEc2oyNjETMBEGCgmSJomT8ixkARkWA2NvbTAeFw0y
15
- MjA3MDQwMDQwNDZaFw0yMzA3MDQwMDQwNDZaMDoxDTALBgNVBAMMBHNqMjYxFDAS
16
- BgoJkiaJk/IsZAEZFgRzajI2MRMwEQYKCZImiZPyLGQBGRYDY29tMIIBIjANBgkq
17
- hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr60Eo/ttCk8GMTMFiPr3GoYMIMFvLak
18
- xSmTk9YGCB6UiEePB4THSSA5w6IPyeaCF/nWkDp3/BAam0eZMWG1IzYQB23TqIM0
19
- 1xzcNRvFsn0aQoQ00k+sj+G83j3T5OOV5OZIlu8xAChMkQmiPd1NXc6uFv+Iacz7
20
- kj+CMsI9YUFdNoU09QY0b+u+Rb6wDYdpyvN60YC30h0h1MeYbvYZJx/iZK4XY5zu
21
- 4O/FL2ChjL2CPCpLZW55ShYyrzphWJwLOJe+FJ/ZBl6YXwrzQM9HKnt4titSNvyU
22
- KzE3L63A3PZvExzLrN9u09kuWLLJfXB2sGOlw3n9t72rJiuBr3/OQQIDAQABo20w
23
- azAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU99dfRjEKFyczTeIz
24
- m3ZsDWrNC80wGAYDVR0RBBEwD4ENc2oyNkBzajI2LmNvbTAYBgNVHRIEETAPgQ1z
25
- ajI2QHNqMjYuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQCsa7k3TABBcyXotr3yCq6f
26
- xsgbMG9FR71c4wRgVNQi9O3jN64fQBbxo//BQlHfPCjs1CeU4es9xdQFfhqXAPXG
27
- P7mK3+qd5jObjh6l3/rDKrTXNS+P+YO/1frlZ6xPjCA8XgGc4y0rhAjZnVBDV6t1
28
- kmdtEmue1s1OxaMakr78XRZDxEuAeLM5fg8MYnlOFygEcAH6lZkTjXavY7s9MXRB
29
- AAMioxgB6J5QhXQ42OSWIzwHZIbSv3DV9Lf5sde50HIW5f9u5jn29TUGDhSWYKkh
30
- LDvy9dfwMMOdIZi75Q8SBBib84AuwhMHIlUv9FcHhh3dXsDDYkrVrpUAwCsG6yCm
31
- -----END CERTIFICATE-----
32
- date: 2022-09-29 00:00:00.000000000 Z
9
+ cert_chain: []
10
+ date: 2026-10-21 00:00:00.000000000 Z
33
11
  dependencies:
34
12
  - !ruby/object:Gem::Dependency
35
13
  name: rspec-core
@@ -37,26 +15,20 @@ dependencies:
37
15
  requirements:
38
16
  - - ">="
39
17
  - !ruby/object:Gem::Version
40
- version: '2'
18
+ version: '3.13'
41
19
  - - "<"
42
20
  - !ruby/object:Gem::Version
43
21
  version: '4'
44
- - - "!="
45
- - !ruby/object:Gem::Version
46
- version: 2.12.0
47
22
  type: :runtime
48
23
  prerelease: false
49
24
  version_requirements: !ruby/object:Gem::Requirement
50
25
  requirements:
51
26
  - - ">="
52
27
  - !ruby/object:Gem::Version
53
- version: '2'
28
+ version: '3.13'
54
29
  - - "<"
55
30
  - !ruby/object:Gem::Version
56
31
  version: '4'
57
- - - "!="
58
- - !ruby/object:Gem::Version
59
- version: 2.12.0
60
32
  - !ruby/object:Gem::Dependency
61
33
  name: bundler
62
34
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +114,12 @@ files:
142
114
  - LICENSE
143
115
  - README.md
144
116
  - lib/rspec_junit_formatter.rb
145
- - lib/rspec_junit_formatter/rspec2.rb
146
117
  - lib/rspec_junit_formatter/rspec3.rb
147
118
  homepage: https://github.com/sj26/rspec_junit_formatter
148
119
  licenses:
149
120
  - MIT
150
121
  metadata:
151
122
  changelog_uri: https://github.com/sj26/rspec_junit_formatter/blob/HEAD/CHANGELOG.md
152
- post_install_message:
153
123
  rdoc_options: []
154
124
  require_paths:
155
125
  - lib
@@ -157,15 +127,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
157
127
  requirements:
158
128
  - - ">="
159
129
  - !ruby/object:Gem::Version
160
- version: 2.3.0
130
+ version: 3.3.0
161
131
  required_rubygems_version: !ruby/object:Gem::Requirement
162
132
  requirements:
163
133
  - - ">="
164
134
  - !ruby/object:Gem::Version
165
135
  version: 2.0.0
166
136
  requirements: []
167
- rubygems_version: 3.3.7
168
- signing_key:
137
+ rubygems_version: 3.6.9
169
138
  specification_version: 4
170
139
  summary: RSpec JUnit XML formatter
171
140
  test_files: []
checksums.yaml.gz.sig DELETED
@@ -1 +0,0 @@
1
- ��[h��bJ��9��$P�6��-�@V
@@ -1,86 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class RSpecJUnitFormatter < RSpec::Core::Formatters::BaseFormatter
4
- attr_reader :started
5
-
6
- def start(example_count)
7
- @started = Time.now
8
- super
9
- end
10
-
11
- def dump_summary(duration, example_count, failure_count, pending_count)
12
- super
13
- xml_dump
14
- end
15
-
16
- private
17
-
18
- def result_of(example)
19
- example.execution_result[:status].to_sym
20
- end
21
-
22
- def example_group_file_path_for(example)
23
- meta = example.metadata
24
- while meta[:example_group]
25
- meta = meta[:example_group]
26
- end
27
- meta[:file_path]
28
- end
29
-
30
- def classname_for(example)
31
- fp = example_group_file_path_for(example)
32
- fp.sub(%r{\.[^/.]+\Z}, "").gsub("/", ".").gsub(/\A\.+|\.+\Z/, "")
33
- end
34
-
35
- def duration_for(example)
36
- example.execution_result[:run_time]
37
- end
38
-
39
- def description_for(example)
40
- example.full_description
41
- end
42
-
43
- def exception_for(example)
44
- example.execution_result[:exception]
45
- end
46
-
47
- def failure_type_for(example)
48
- exception_for(example).class.name
49
- end
50
-
51
- def failure_message_for(example)
52
- strip_diff_colors(exception_for(example).to_s)
53
- end
54
-
55
- def failure_for(example)
56
- exception = exception_for(example)
57
- message = strip_diff_colors(exception.message)
58
- backtrace = format_backtrace(exception.backtrace, example)
59
-
60
- if shared_group = find_shared_group(example)
61
- backtrace << "Shared Example Group: \"#{shared_group.metadata[:shared_group_name]}\" called from #{shared_group.metadata[:example_group][:location]}"
62
- end
63
-
64
- "#{message}\n#{backtrace.join("\n")}"
65
- end
66
-
67
- def error_count
68
- 0
69
- end
70
-
71
- def find_shared_group(example)
72
- group_and_parent_groups(example).find { |group| group.metadata[:shared_group_name] }
73
- end
74
-
75
- def group_and_parent_groups(example)
76
- example.example_group.parent_groups + [example.example_group]
77
- end
78
-
79
- def stdout_for(example)
80
- example.metadata[:stdout]
81
- end
82
-
83
- def stderr_for(example)
84
- example.metadata[:stderr]
85
- end
86
- end
data.tar.gz.sig DELETED
@@ -1,2 +0,0 @@
1
- kb�u�(5����\���<F�,���uЯ�vx��}-~rBFl���;k�;P�K1t��{<��4�rZ+۱�H��"r��W�żi��q�ws�[����Z��T�E������ D���_
2
- O9�&�Eh�R��:V�,����}����B��
metadata.gz.sig DELETED
Binary file