rspec_junit_formatter_bitbucket 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.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.md +126 -0
- data/lib/rspec_junit_formatter_bitbucket.rb +20 -0
- data/lib/rspec_junit_formatter_bitbucket/info.rb +33 -0
- data/lib/rspec_junit_formatter_bitbucket/init.rb +355 -0
- metadata +184 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 406b38492456241386e52eba83fca1ae1fe3835be224415ffc7d465d5ab5dba0
|
4
|
+
data.tar.gz: 9c7b748c2d2b70a17cec376f65beb996164306926653d86a4e815fce93e8f443
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2ac815d3b5d2aa7b58a73c5fec13f1675d24277663998bf3da4c07bf7ada2bd6b3b206f6693b33951ed0a81b32889e2baadfe116753459ca712632ae3d29083f
|
7
|
+
data.tar.gz: 6788c28e17df99db6475ebdb4cf8dfd2072ddd3c85499fdd22a1c1356393876698c6f917d709eb1f67ed27556d5427ca991f9e503ddb32bcb803c686ccd991b4
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011-2018 Samuel Cochran
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
# RSpec JUnit Formatter
|
2
|
+
|
3
|
+
__FORK to project : [sj26](https://github.com/sj26/rspec_junit_formatter)__
|
4
|
+
|
5
|
+
Use for pipeline bitbucket. Apply rules : http://reflex.gforge.inria.fr/xunit.html#xunitReport
|
6
|
+
|
7
|
+
[](https://travis-ci.org/sj26/rspec_junit_formatter)
|
8
|
+
[](https://rubygems.org/gems/rspec_junit_formatter)
|
9
|
+
|
10
|
+
[RSpec][rspec] 2 & 3 results that your CI can read. [Jenkins][jenkins-junit], [Buildkite][buildkite-junit], [CircleCI][circleci-junit], and probably more, too.
|
11
|
+
|
12
|
+
[rspec]: http://rspec.info/
|
13
|
+
[jenkins-junit]: https://jenkins.io/doc/pipeline/steps/junit/
|
14
|
+
[buildkite-junit]: https://github.com/buildkite/rspec-junit-example
|
15
|
+
[circleci-junit]: https://circleci.com/docs/2.0/collect-test-data/
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
Install the gem:
|
20
|
+
|
21
|
+
```sh
|
22
|
+
gem install rspec_junit_formatter
|
23
|
+
```
|
24
|
+
|
25
|
+
Use it:
|
26
|
+
|
27
|
+
```sh
|
28
|
+
rspec --format RspecJunitFormatter --out rspec.xml
|
29
|
+
```
|
30
|
+
|
31
|
+
You'll get an XML file `rspec.xml` with your results in it.
|
32
|
+
|
33
|
+
You can use it in combination with other [formatters][rspec-formatters], too:
|
34
|
+
|
35
|
+
```sh
|
36
|
+
rspec --format progress --format RspecJunitFormatter --out rspec.xml
|
37
|
+
```
|
38
|
+
|
39
|
+
[rspec-formatters]: https://relishapp.com/rspec/rspec-core/v/3-6/docs/formatters
|
40
|
+
|
41
|
+
### Using in your project with Bundler
|
42
|
+
|
43
|
+
Add it to your Gemfile if you're using [Bundler][bundler]. Put it in the same groups as rspec.
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
group :test do
|
47
|
+
gem "rspec"
|
48
|
+
gem "rspec_junit_formatter"
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
Put the same arguments as the commands above in [your `.rspec`][rspec-file]:
|
53
|
+
|
54
|
+
```sh
|
55
|
+
--format RspecJunitFormatter
|
56
|
+
--out rspec.xml
|
57
|
+
```
|
58
|
+
[bundler]: https://bundler.io
|
59
|
+
[rspec-file]: https://relishapp.com/rspec/rspec-core/v/3-6/docs/configuration/read-command-line-configuration-options-from-files
|
60
|
+
|
61
|
+
### Parallel tests
|
62
|
+
|
63
|
+
For use with `parallel_tests`, add `$TEST_ENV_NUMBER` in the output file option (in `.rspec` or `.rspec_parallel`) to avoid concurrent process write conflicts.
|
64
|
+
|
65
|
+
```sh
|
66
|
+
--format RspecJunitFormatter
|
67
|
+
--out tmp/rspec<%= ENV["TEST_ENV_NUMBER"] %>.xml
|
68
|
+
```
|
69
|
+
|
70
|
+
The formatter includes `$TEST_ENV_NUMBER` in the test suite name within the XML, too.
|
71
|
+
|
72
|
+
### Capturing output
|
73
|
+
|
74
|
+
If you like, you can capture the standard output and error streams of each test into the `:stdout` and `:stderr` example metadata which will be added to the junit report, e.g.:
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
# spec_helper.rb
|
78
|
+
|
79
|
+
RSpec.configure do |config|
|
80
|
+
# register around filter that captures stdout and stderr
|
81
|
+
config.around(:each) do |example|
|
82
|
+
$stdout = StringIO.new
|
83
|
+
$stderr = StringIO.new
|
84
|
+
|
85
|
+
example.run
|
86
|
+
|
87
|
+
example.metadata[:stdout] = $stdout.string
|
88
|
+
example.metadata[:stderr] = $stderr.string
|
89
|
+
|
90
|
+
$stdout = STDOUT
|
91
|
+
$stderr = STDERR
|
92
|
+
end
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
## Caveats
|
97
|
+
|
98
|
+
* 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`.
|
99
|
+
|
100
|
+
[xml-charsets]: https://www.w3.org/TR/xml/#charsets
|
101
|
+
|
102
|
+
## Roadmap
|
103
|
+
|
104
|
+
* It would be nice to split things up into individual test suites, although would this correspond to example groups? The subject? The spec file? Not sure yet.
|
105
|
+
|
106
|
+
## Development
|
107
|
+
|
108
|
+
Run the specs with `bundle exec rake`, which uses [Appraisal][appraisal] to run the specs against all supported versions of rspec.
|
109
|
+
|
110
|
+
[appraisal]: https://github.com/thoughtbot/appraisal
|
111
|
+
|
112
|
+
## Releasing
|
113
|
+
|
114
|
+
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.
|
115
|
+
|
116
|
+
## License
|
117
|
+
|
118
|
+
The MIT License, see [LICENSE](./LICENSE).
|
119
|
+
|
120
|
+
## Thanks
|
121
|
+
|
122
|
+
Inspired by the work of [Diego Souza][dgvncsz0f] on [RSpec Formatters][dgvncsz0f/rspec_formatters] after frustration with [CI Reporter][ci_reporter].
|
123
|
+
|
124
|
+
[dgvncsz0f]: https://github.com/dgvncsz0f
|
125
|
+
[dgvncsz0f/rspec_formatters]: https://github.com/dgvncsz0f/rspec_formatters
|
126
|
+
[ci_reporter]: https://github.com/nicksieger/ci_reporter
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
require 'rspec/core'
|
7
|
+
require 'rspec/core/formatters/base_formatter'
|
8
|
+
|
9
|
+
require 'rspec_junit_formatter_bitbucket/init'
|
10
|
+
|
11
|
+
=begin
|
12
|
+
if Gem::Version.new(RSpec::Core::Version::STRING) >= Gem::Version.new('3')
|
13
|
+
require 'rspec-junit-formatter/rspec/version-3'
|
14
|
+
else
|
15
|
+
require 'rspec-junit-formatter/rspec/version-2'
|
16
|
+
end
|
17
|
+
=end
|
18
|
+
|
19
|
+
# Use alias for symplify call formatter in RSpec
|
20
|
+
JUnit = RspecJunitFormatterBitbucket::Init
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Define constant to this gem
|
4
|
+
module RspecJunitFormatterBitbucket
|
5
|
+
module Info
|
6
|
+
# Define version
|
7
|
+
VERSION = '0.1.0'
|
8
|
+
|
9
|
+
# Define Name
|
10
|
+
GEM_NAME = 'rspec_junit_formatter_bitbucket'
|
11
|
+
|
12
|
+
# Authors
|
13
|
+
AUTHORS = ['VAILLANT Jeremy'].freeze
|
14
|
+
|
15
|
+
# Emails
|
16
|
+
EMAILS = ['jeremy@dazzl.tv'].freeze
|
17
|
+
|
18
|
+
# Licence
|
19
|
+
LICENSE = 'MIT'
|
20
|
+
|
21
|
+
# Define a summary description to gem
|
22
|
+
SUMMARY = 'RSpec Junit Formatter'
|
23
|
+
|
24
|
+
# Define a long description to gem
|
25
|
+
DESCRIPTION = <<-DESC
|
26
|
+
RSpec Junit Formatter results that your CI can read in Bitbucket Pipeline.
|
27
|
+
Use convention http://reflex.gforge.inria.fr
|
28
|
+
DESC
|
29
|
+
|
30
|
+
# Define homepage
|
31
|
+
HOMEPAGE = 'https://github.com/dazzl-tv/rspec_junit_formatter'
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,355 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Metrics/ClassLength, Style/GuardClause, Metrics/AbcSize
|
4
|
+
# rubocop:disable Metrics/MethodLength
|
5
|
+
|
6
|
+
# Dumps rspec results as a JUnit XML file.
|
7
|
+
# Based on XML schema: http://windyroad.org/dl/Open%20Source/JUnit.xsd
|
8
|
+
module RspecJunitFormatterBitbucket
|
9
|
+
class Init < RSpec::Core::Formatters::BaseFormatter
|
10
|
+
RSpec::Core::Formatters.register self,
|
11
|
+
:start,
|
12
|
+
:stop,
|
13
|
+
:dump_summary
|
14
|
+
|
15
|
+
def start(notification)
|
16
|
+
@start_notification = notification
|
17
|
+
@started = Time.now
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def stop(notification)
|
22
|
+
@examples_notification = notification
|
23
|
+
end
|
24
|
+
|
25
|
+
def dump_summary(notification)
|
26
|
+
@summary_notification = notification
|
27
|
+
without_color { xml_dump }
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :started
|
33
|
+
|
34
|
+
def example_count
|
35
|
+
@summary_notification.example_count
|
36
|
+
end
|
37
|
+
|
38
|
+
def pending_count
|
39
|
+
@summary_notification.pending_count
|
40
|
+
end
|
41
|
+
|
42
|
+
def failure_count
|
43
|
+
@summary_notification.failure_count
|
44
|
+
end
|
45
|
+
|
46
|
+
def duration
|
47
|
+
@summary_notification.duration
|
48
|
+
end
|
49
|
+
|
50
|
+
def examples
|
51
|
+
@examples_notification.notifications
|
52
|
+
end
|
53
|
+
|
54
|
+
def result_of(notification)
|
55
|
+
notification.example.execution_result.status
|
56
|
+
end
|
57
|
+
|
58
|
+
def example_group_file_path_for(notification)
|
59
|
+
metadata = notification.example.metadata[:example_group]
|
60
|
+
while parent_metadata = metadata[:parent_example_group]
|
61
|
+
metadata = parent_metadata
|
62
|
+
end
|
63
|
+
metadata[:file_path]
|
64
|
+
end
|
65
|
+
|
66
|
+
def classname_for(notification)
|
67
|
+
fp = example_group_file_path_for(notification)
|
68
|
+
fp.sub(%r{\.[^/]*\Z}, '').tr('/', '.').gsub(/\A\.+|\.+\Z/, '')
|
69
|
+
end
|
70
|
+
|
71
|
+
def duration_for(notification)
|
72
|
+
notification.example.execution_result.run_time
|
73
|
+
end
|
74
|
+
|
75
|
+
def description_for(notification)
|
76
|
+
notification.example.full_description
|
77
|
+
end
|
78
|
+
|
79
|
+
def failure_type_for(example)
|
80
|
+
exception_for(example).class.name
|
81
|
+
end
|
82
|
+
|
83
|
+
def failure_message_for(example)
|
84
|
+
strip_diff_colors(exception_for(example).to_s)
|
85
|
+
end
|
86
|
+
|
87
|
+
def failure_for(notification)
|
88
|
+
strip_diff_colors(notification.message_lines.join("\n")) << \
|
89
|
+
"\n" << notification.formatted_backtrace.join("\n")
|
90
|
+
end
|
91
|
+
|
92
|
+
def exception_for(notification)
|
93
|
+
notification.example.execution_result.exception
|
94
|
+
end
|
95
|
+
|
96
|
+
# rspec makes it really difficult to swap in configuration temporarily due to
|
97
|
+
# the way it cascades defaults, command line arguments, and user
|
98
|
+
# configuration. This method makes sure configuration gets swapped in
|
99
|
+
# correctly, but also that the original state is definitely restored.
|
100
|
+
def swap_rspec_configuration(key, value)
|
101
|
+
unset = Object.new
|
102
|
+
force = RSpec.configuration.send(:value_for, key) { unset }
|
103
|
+
previous = check_swap(key, value, force, unset)
|
104
|
+
yield
|
105
|
+
ensure
|
106
|
+
ensure_swap(key, force, previous, unset)
|
107
|
+
end
|
108
|
+
|
109
|
+
def check_swap(key, value, force, unset)
|
110
|
+
if unset.equal?(force)
|
111
|
+
previous = RSpec.configuration.send(key)
|
112
|
+
RSpec.configuration.send(:"#{key}=", value)
|
113
|
+
else
|
114
|
+
RSpec.configuration.force(key => value)
|
115
|
+
end
|
116
|
+
previous
|
117
|
+
end
|
118
|
+
|
119
|
+
def ensure_swap(key, force, previous, unset)
|
120
|
+
if unset.equal?(force)
|
121
|
+
RSpec.configuration.send(:"#{key}=", previous)
|
122
|
+
else
|
123
|
+
RSpec.configuration.force(key => force)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Completely gross hack for absolutely forcing off colorising for the
|
128
|
+
# duration of a block.
|
129
|
+
if RSpec.configuration.respond_to?(:color_mode=)
|
130
|
+
def without_color(&block)
|
131
|
+
swap_rspec_configuration(:color_mode, :off, &block)
|
132
|
+
end
|
133
|
+
elsif RSpec.configuration.respond_to?(:color=)
|
134
|
+
def without_color(&block)
|
135
|
+
swap_rspec_configuration(:color, false, &block)
|
136
|
+
end
|
137
|
+
else
|
138
|
+
warn 'rspec_junit_formatter cannot prevent colorising due ' \
|
139
|
+
'to an unexpected RSpec.configuration format'
|
140
|
+
def without_color
|
141
|
+
yield
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def stdout_for(example_notification)
|
146
|
+
example_notification.example.metadata[:stdout]
|
147
|
+
end
|
148
|
+
|
149
|
+
def stderr_for(example_notification)
|
150
|
+
example_notification.example.metadata[:stderr]
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def xml_dump
|
156
|
+
output << %(<?xml version="1.0" encoding="UTF-8"?>\n)
|
157
|
+
output << %(<test-suite)
|
158
|
+
output << %( name="rspec#{escape(ENV['TEST_ENV_NUMBER'].to_s)}")
|
159
|
+
output << %( tests="#{example_count}")
|
160
|
+
output << %( skipped="#{pending_count}")
|
161
|
+
output << %( failures="#{failure_count}")
|
162
|
+
output << %( errors="0")
|
163
|
+
output << %( time="#{escape(format('%.6f', duration))}")
|
164
|
+
output << %( timestamp="#{escape(started.iso8601)}")
|
165
|
+
output << %( hostname="#{escape(Socket.gethostname)}")
|
166
|
+
output << %(>\n)
|
167
|
+
output << %(<properties>\n)
|
168
|
+
output << %(<property)
|
169
|
+
output << %( name="seed")
|
170
|
+
output << %( value="#{escape(RSpec.configuration.seed.to_s)}")
|
171
|
+
output << %(/>\n)
|
172
|
+
output << %(</properties>\n)
|
173
|
+
xml_dump_examples
|
174
|
+
output << %(</test-suite>\n)
|
175
|
+
end
|
176
|
+
|
177
|
+
def xml_dump_examples
|
178
|
+
examples.each do |example|
|
179
|
+
case result_of(example)
|
180
|
+
when :pending
|
181
|
+
xml_dump_pending(example)
|
182
|
+
when :failed
|
183
|
+
xml_dump_failed(example)
|
184
|
+
else
|
185
|
+
xml_dump_example(example)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def xml_dump_pending(example)
|
191
|
+
xml_dump_example(example) do
|
192
|
+
output << %(<skipped/>)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def xml_dump_failed(example)
|
197
|
+
xml_dump_example(example) do
|
198
|
+
output << %(<failure)
|
199
|
+
output << %( message="#{escape(failure_message_for(example))}")
|
200
|
+
output << %( type="#{escape(failure_type_for(example))}")
|
201
|
+
output << %(>)
|
202
|
+
output << escape(failure_for(example))
|
203
|
+
output << %(</failure>)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def xml_dump_example(example)
|
208
|
+
output << %(<test-case)
|
209
|
+
output << %( classname="#{escape(classname_for(example))}")
|
210
|
+
output << %( name="#{escape(description_for(example))}")
|
211
|
+
output << %( file="#{escape(example_group_file_path_for(example))}")
|
212
|
+
output << %( time="#{escape(format('%.6f', duration_for(example)))}")
|
213
|
+
output << %(>)
|
214
|
+
yield if block_given?
|
215
|
+
xml_dump_output(example)
|
216
|
+
output << %(</test-case>\n)
|
217
|
+
end
|
218
|
+
|
219
|
+
def xml_dump_output(example)
|
220
|
+
if (stdout = stdout_for(example)) && !stdout.empty?
|
221
|
+
output << %(<system-out>)
|
222
|
+
output << escape(stdout)
|
223
|
+
output << %(</system-out>)
|
224
|
+
end
|
225
|
+
|
226
|
+
if (stderr = stderr_for(example)) && !stderr.empty?
|
227
|
+
output << %(<system-err>)
|
228
|
+
output << escape(stderr)
|
229
|
+
output << %(</system-err>)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Inversion of character range from https://www.w3.org/TR/xml/#charsets
|
234
|
+
=begin
|
235
|
+
ILLEGAL_REGEXP = Regexp.new(
|
236
|
+
'[^' <<
|
237
|
+
'\u{9}' << # => \t
|
238
|
+
'\u{a}' << # => \n
|
239
|
+
'\u{d}' << # => \r
|
240
|
+
'\u{20}-\u{d7ff}' <<
|
241
|
+
'\u{e000}-\u{fffd}' <<
|
242
|
+
'\u{10000}-\u{10ffff}' <<
|
243
|
+
']'
|
244
|
+
)
|
245
|
+
=end
|
246
|
+
|
247
|
+
# rubocop:disable Style/FormatStringToken
|
248
|
+
# Replace illegals with a Ruby-like escape
|
249
|
+
ILLEGAL_REPLACEMENT = Hash.new do |_, c|
|
250
|
+
x = c.ord
|
251
|
+
if x <= 0xff
|
252
|
+
'\\x%02X'.freeze % x
|
253
|
+
elsif x <= 0xffff
|
254
|
+
'\\u%04X'.freeze % x
|
255
|
+
else
|
256
|
+
'\\u{%X}'.freeze % x
|
257
|
+
end.freeze
|
258
|
+
end.update(
|
259
|
+
"\0".freeze => '\\0'.freeze,
|
260
|
+
"\a".freeze => '\\a'.freeze,
|
261
|
+
"\b".freeze => '\\b'.freeze,
|
262
|
+
"\f".freeze => '\\f'.freeze,
|
263
|
+
"\v".freeze => '\\v'.freeze,
|
264
|
+
"\e".freeze => '\\e'.freeze
|
265
|
+
).freeze
|
266
|
+
# rubocop:enable Style/FormatStringToken
|
267
|
+
|
268
|
+
# Discouraged characters from https://www.w3.org/TR/xml/#charsets
|
269
|
+
# Plus special characters with well-known entity replacements
|
270
|
+
=begin
|
271
|
+
DISCOURAGED_REGEXP = Regexp.new(
|
272
|
+
'[' \
|
273
|
+
"\u{22}" << # => "
|
274
|
+
"\u{26}" << # => &
|
275
|
+
"\u{27}" << # => '
|
276
|
+
"\u{3c}" << # => <
|
277
|
+
"\u{3e}" << # => >
|
278
|
+
"\u{7f}-\u{84}" \
|
279
|
+
"\u{86}-\u{9f}" \
|
280
|
+
"\u{fdd0}-\u{fdef}" \
|
281
|
+
"\u{1fffe}-\u{1ffff}" \
|
282
|
+
"\u{2fffe}-\u{2ffff}" \
|
283
|
+
"\u{3fffe}-\u{3ffff}" \
|
284
|
+
"\u{4fffe}-\u{4ffff}" \
|
285
|
+
"\u{5fffe}-\u{5ffff}" \
|
286
|
+
"\u{6fffe}-\u{6ffff}" \
|
287
|
+
"\u{7fffe}-\u{7ffff}" \
|
288
|
+
"\u{8fffe}-\u{8ffff}" \
|
289
|
+
"\u{9fffe}-\u{9ffff}" \
|
290
|
+
"\u{afffe}-\u{affff}" \
|
291
|
+
"\u{bfffe}-\u{bffff}" \
|
292
|
+
"\u{cfffe}-\u{cffff}" \
|
293
|
+
"\u{dfffe}-\u{dffff}" \
|
294
|
+
"\u{efffe}-\u{effff}" \
|
295
|
+
"\u{ffffe}-\u{fffff}" \
|
296
|
+
"\u{10fffe}-\u{10ffff}" \
|
297
|
+
']'
|
298
|
+
)
|
299
|
+
=end
|
300
|
+
|
301
|
+
# Translate well-known entities, or use generic unicode hex entity
|
302
|
+
DISCOURAGED_REPLACEMENTS = Hash.new do |_, c|
|
303
|
+
"&#x#{c.ord.to_s(16)};".freeze
|
304
|
+
end.update(
|
305
|
+
'"'.freeze => '"'.freeze,
|
306
|
+
'&'.freeze => '&'.freeze,
|
307
|
+
"'".freeze => '''.freeze,
|
308
|
+
'<'.freeze => '<'.freeze,
|
309
|
+
'>'.freeze => '>'.freeze
|
310
|
+
).freeze
|
311
|
+
|
312
|
+
def escape(text)
|
313
|
+
# Make sure it's utf-8, replace illegal characters with ruby-like escapes,
|
314
|
+
# and replace special and discouraged characters with entities
|
315
|
+
text.to_s.encode(Encoding::UTF_8)
|
316
|
+
# .gsub(DISCOURAGED_REGEXP, DISCOURAGED_REPLACEMENTS)
|
317
|
+
# .gsub(ILLEGAL_REGEXP, ILLEGAL_REPLACEMENT)
|
318
|
+
end
|
319
|
+
|
320
|
+
# rubocop:disable Metrics/LineLength
|
321
|
+
STRIP_DIFF_COLORS_BLOCK_REGEXP = /^ ( [ ]* ) Diff: (?: \e\[ 0 m )? (?: \n \1 \e\[ \d+ (?: ; \d+ )* m .* )* /x.freeze
|
322
|
+
STRIP_DIFF_COLORS_CODES_REGEXP = /\e\[ \d+ (?: ; \d+ )* m/x.freeze
|
323
|
+
# rubocop:enable Metrics/LineLength
|
324
|
+
|
325
|
+
def strip_diff_colors(string)
|
326
|
+
# XXX: RSpec diffs are appended to the message lines fairly early and will
|
327
|
+
# contain ANSI escape codes for colorizing terminal output if the global
|
328
|
+
# rspec configuration is turned on, regardless of which notification lines
|
329
|
+
# we ask for. We need to strip the codes from the diff part of the message
|
330
|
+
# for XML output here.
|
331
|
+
#
|
332
|
+
# We also only want to target the diff hunks because the failure message
|
333
|
+
# itself might legitimately contain ansi escape codes.
|
334
|
+
#
|
335
|
+
string.sub(STRIP_DIFF_COLORS_BLOCK_REGEXP) do |match|
|
336
|
+
match.gsub(STRIP_DIFF_COLORS_CODES_REGEXP, ''.freeze)
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
|
342
|
+
if defined?(RSpec::Core::Notifications::NullColorizer) &&
|
343
|
+
RSpec::Core::Notifications::NullColorizer.is_a?(Class) &&
|
344
|
+
!RSpec::Core::Notifications::NullColorizer.respond_to?(:wrap)
|
345
|
+
RSpec::Core::Notifications::NullColorizer.class_eval do
|
346
|
+
def self.wrap(*args)
|
347
|
+
new.wrap(*args)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
# Create an alias for respect case
|
353
|
+
# RspecJunitFormatter = RSpecJUnitFormatter
|
354
|
+
# rubocop:enable Metrics/ClassLength, Style/GuardClause, Metrics/AbcSize
|
355
|
+
# rubocop:enable Metrics/MethodLength
|
metadata
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rspec_junit_formatter_bitbucket
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- VAILLANT Jeremy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-05-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2'
|
20
|
+
- - "!="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.12.0
|
23
|
+
- - "<"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '4'
|
26
|
+
type: :runtime
|
27
|
+
prerelease: false
|
28
|
+
version_requirements: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2'
|
33
|
+
- - "!="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 2.12.0
|
36
|
+
- - "<"
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '4'
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: bundler
|
41
|
+
requirement: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - "~>"
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.17'
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 1.17.3
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.17'
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 1.17.3
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: appraisal
|
61
|
+
requirement: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - "~>"
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '2.2'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - "~>"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '2.2'
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: nokogiri
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '1.8'
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.8.2
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.8'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 1.8.2
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: rake
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '12.3'
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 12.3.2
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '12.3'
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 12.3.2
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: coderay
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '1.1'
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 1.1.2
|
123
|
+
type: :development
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '1.1'
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 1.1.2
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: pry
|
135
|
+
requirement: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: 0.12.2
|
140
|
+
type: :development
|
141
|
+
prerelease: false
|
142
|
+
version_requirements: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - "~>"
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 0.12.2
|
147
|
+
description: |2
|
148
|
+
RSpec Junit Formatter results that your CI can read in Bitbucket Pipeline.
|
149
|
+
Use convention http://reflex.gforge.inria.fr
|
150
|
+
email:
|
151
|
+
- jeremy@dazzl.tv
|
152
|
+
executables: []
|
153
|
+
extensions: []
|
154
|
+
extra_rdoc_files: []
|
155
|
+
files:
|
156
|
+
- LICENSE
|
157
|
+
- README.md
|
158
|
+
- lib/rspec_junit_formatter_bitbucket.rb
|
159
|
+
- lib/rspec_junit_formatter_bitbucket/info.rb
|
160
|
+
- lib/rspec_junit_formatter_bitbucket/init.rb
|
161
|
+
homepage: https://github.com/dazzl-tv/rspec_junit_formatter
|
162
|
+
licenses:
|
163
|
+
- MIT
|
164
|
+
metadata: {}
|
165
|
+
post_install_message:
|
166
|
+
rdoc_options: []
|
167
|
+
require_paths:
|
168
|
+
- lib
|
169
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 2.0.0
|
174
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: 2.0.0
|
179
|
+
requirements: []
|
180
|
+
rubygems_version: 3.0.3
|
181
|
+
signing_key:
|
182
|
+
specification_version: 4
|
183
|
+
summary: RSpec Junit Formatter
|
184
|
+
test_files: []
|