rspec_junit_formatter_bitbucket 0.1.0 → 0.2.0.pre.170
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 +4 -4
- data/README.md +15 -30
- data/lib/rspec_junit_formatter_bitbucket/attribute.rb +29 -0
- data/lib/rspec_junit_formatter_bitbucket/format.rb +108 -0
- data/lib/rspec_junit_formatter_bitbucket/info.rb +1 -1
- data/lib/rspec_junit_formatter_bitbucket/j_unit.rb +140 -0
- data/lib/rspec_junit_formatter_bitbucket/xml.rb +113 -0
- data/lib/rspec_junit_formatter_bitbucket.rb +4 -12
- metadata +50 -19
- data/lib/rspec_junit_formatter_bitbucket/init.rb +0 -355
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da625be220376cea7a09f0c1870b2bea24b5f40e825a8c7296ed76318ecf1cff
|
4
|
+
data.tar.gz: c9ae2324d2e151ee747eebd08ffa7245bec2860414392d44731a3234e4d0f797
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0524b387088bbcc39230e84ac964eeef48bf77760abc9b27ff2241b7a4edc44687a7506b8755d8e260ce5bbc8b0cb75b45f3e1decc0adb268ddcbee6313d950f
|
7
|
+
data.tar.gz: 8bc904f3bdbe9d690bd1daa57151e2fd3a49b1b1de72335a8cd6e2686577a2423e1c1785006cb52555e57a1f0df775a6cf4081acc3b69f947a2105d52126810a
|
data/README.md
CHANGED
@@ -1,42 +1,39 @@
|
|
1
|
-
# RSpec JUnit Formatter
|
1
|
+
# RSpec JUnit Formatter | [](https://travis-ci.org/dazzl-tv/rspec_junit_formatter) [](https://badge.fury.io/rb/rspec_junit_formatter_bitbucket)
|
2
2
|
|
3
3
|
__FORK to project : [sj26](https://github.com/sj26/rspec_junit_formatter)__
|
4
4
|
|
5
5
|
Use for pipeline bitbucket. Apply rules : http://reflex.gforge.inria.fr/xunit.html#xunitReport
|
6
6
|
|
7
|
-
|
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/
|
7
|
+
Rspec 3 (remove rspec 2 compatibility) that your CI (Forked for Bitbucket pipeline).
|
16
8
|
|
17
9
|
## Usage
|
18
10
|
|
19
11
|
Install the gem:
|
20
12
|
|
21
13
|
```sh
|
22
|
-
gem install
|
14
|
+
gem install rspec_junit_formatter_bitbucket
|
23
15
|
```
|
24
16
|
|
25
17
|
Use it:
|
26
18
|
|
27
19
|
```sh
|
28
|
-
|
20
|
+
# Use RSpec directly
|
21
|
+
rspec --format JUnit --out ./tmp/test-reports/rspec/report.xml
|
22
|
+
|
23
|
+
# use with bundle
|
24
|
+
export SPEC_OPTS=" --require rspec_junit_formatter_bitbucket --format RspecJunitFormatterBitbucket::Init --out ./tmp/test-reports/rspec/report.xml"
|
25
|
+
bundle exec rake spec
|
29
26
|
```
|
30
27
|
|
31
|
-
You'll get an XML file `
|
28
|
+
You'll get an XML file `report.xml` with your results in it.
|
32
29
|
|
33
30
|
You can use it in combination with other [formatters][rspec-formatters], too:
|
34
31
|
|
35
32
|
```sh
|
36
|
-
rspec --format progress --format
|
33
|
+
rspec --format progress --format RspecJunitFormatterBitbucket::Init --out rspec.xml
|
37
34
|
```
|
38
35
|
|
39
|
-
[rspec-formatters]: https://relishapp.com/rspec/rspec-core/v/3-
|
36
|
+
[rspec-formatters]: https://relishapp.com/rspec/rspec-core/v/3-8/docs/formatters/custom-formatters
|
40
37
|
|
41
38
|
### Using in your project with Bundler
|
42
39
|
|
@@ -45,14 +42,14 @@ Add it to your Gemfile if you're using [Bundler][bundler]. Put it in the same gr
|
|
45
42
|
```ruby
|
46
43
|
group :test do
|
47
44
|
gem "rspec"
|
48
|
-
gem "
|
45
|
+
gem "rspec_junit_formatter_bitbucket"
|
49
46
|
end
|
50
47
|
```
|
51
48
|
|
52
49
|
Put the same arguments as the commands above in [your `.rspec`][rspec-file]:
|
53
50
|
|
54
51
|
```sh
|
55
|
-
--format
|
52
|
+
--format RspecJunitFormatterBitbucket::Init
|
56
53
|
--out rspec.xml
|
57
54
|
```
|
58
55
|
[bundler]: https://bundler.io
|
@@ -99,28 +96,16 @@ end
|
|
99
96
|
|
100
97
|
[xml-charsets]: https://www.w3.org/TR/xml/#charsets
|
101
98
|
|
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
99
|
## Development
|
107
100
|
|
108
101
|
Run the specs with `bundle exec rake`, which uses [Appraisal][appraisal] to run the specs against all supported versions of rspec.
|
109
102
|
|
110
103
|
[appraisal]: https://github.com/thoughtbot/appraisal
|
111
104
|
|
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
105
|
## License
|
117
106
|
|
118
107
|
The MIT License, see [LICENSE](./LICENSE).
|
119
108
|
|
120
109
|
## Thanks
|
121
110
|
|
122
|
-
|
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
|
111
|
+
And thanks [sj26](https://github.com/sj26)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Lint/AssignmentInCondition
|
4
|
+
module RspecJunitFormatterBitbucket
|
5
|
+
# Format attribute to xml
|
6
|
+
module Attribute
|
7
|
+
def self.classname_for(notification)
|
8
|
+
fp = example_group_file_path_for(notification)
|
9
|
+
fp.sub(%r{\.[^/]*\Z}, '').tr('/', '.').gsub(/\A\.+|\.+\Z/, '')
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.description_for(notification)
|
13
|
+
notification.example.full_description
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.example_group_file_path_for(notification)
|
17
|
+
metadata = notification.example.metadata[:example_group]
|
18
|
+
while parent_metadata = metadata[:parent_example_group]
|
19
|
+
metadata = parent_metadata
|
20
|
+
end
|
21
|
+
metadata[:file_path]
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.duration_for(notification)
|
25
|
+
notification.example.execution_result.run_time
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
# rubocop:enable Lint/AssignmentInCondition
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
module RspecJunitFormatterBitbucket
|
4
|
+
# Make sure it's utf-8, replace illegal characters with
|
5
|
+
# ruby-like escapes, and replace special and discouraged
|
6
|
+
# characters with entities
|
7
|
+
module Format
|
8
|
+
# Inversion of character range from https://www.w3.org/TR/xml/#charsets
|
9
|
+
ILLEGAL_REGEXP = Regexp.new(
|
10
|
+
'\[\^' \
|
11
|
+
'\u{9}' \
|
12
|
+
'\u{a}' \
|
13
|
+
'\u{d}' \
|
14
|
+
'\u{20}-\u{d7ff}' \
|
15
|
+
'\u{e000}-\u{fffd}' \
|
16
|
+
'\u{10000}-\u{10ffff}' \
|
17
|
+
'\]'
|
18
|
+
)
|
19
|
+
|
20
|
+
# Replace illegals with a Ruby-like escape
|
21
|
+
ILLEGAL_REPLACEMENT = Hash.new do |_, c|
|
22
|
+
x = c.ord
|
23
|
+
if x <= 0xff
|
24
|
+
'\\x%02X'.freeze % x
|
25
|
+
elsif x <= 0xffff
|
26
|
+
'\\u%04X'.freeze % x
|
27
|
+
else
|
28
|
+
'\\u{%<X>}'.freeze % x
|
29
|
+
end.freeze
|
30
|
+
end.update(
|
31
|
+
"\0".freeze => '\\0'.freeze,
|
32
|
+
"\a".freeze => '\\a'.freeze,
|
33
|
+
"\b".freeze => '\\b'.freeze,
|
34
|
+
"\f".freeze => '\\f'.freeze,
|
35
|
+
"\v".freeze => '\\v'.freeze,
|
36
|
+
"\e".freeze => '\\e'.freeze
|
37
|
+
).freeze
|
38
|
+
|
39
|
+
# Discouraged characters from https://www.w3.org/TR/xml/#charsets
|
40
|
+
# Plus special characters with well-known entity replacements
|
41
|
+
DISCOURAGED_REGEXP = Regexp.new(
|
42
|
+
'[' \
|
43
|
+
'\u{22}' \
|
44
|
+
'\u{26}' \
|
45
|
+
'\u{27}' \
|
46
|
+
'\u{3c}' \
|
47
|
+
'\u{3e}' \
|
48
|
+
'\u{7f}-\u{84}' \
|
49
|
+
'\u{86}-\u{9f}' \
|
50
|
+
'\u{fdd0}-\u{fdef}' \
|
51
|
+
'\u{1fffe}-\u{1ffff}' \
|
52
|
+
'\u{2fffe}-\u{2ffff}' \
|
53
|
+
'\u{3fffe}-\u{3ffff}' \
|
54
|
+
'\u{4fffe}-\u{4ffff}' \
|
55
|
+
'\u{5fffe}-\u{5ffff}' \
|
56
|
+
'\u{6fffe}-\u{6ffff}' \
|
57
|
+
'\u{7fffe}-\u{7ffff}' \
|
58
|
+
'\u{8fffe}-\u{8ffff}' \
|
59
|
+
'\u{9fffe}-\u{9ffff}' \
|
60
|
+
'\u{afffe}-\u{affff}' \
|
61
|
+
'\u{bfffe}-\u{bffff}' \
|
62
|
+
'\u{cfffe}-\u{cffff}' \
|
63
|
+
'\u{dfffe}-\u{dffff}' \
|
64
|
+
'\u{efffe}-\u{effff}' \
|
65
|
+
'\u{ffffe}-\u{fffff}' \
|
66
|
+
'\u{10fffe}-\u{10ffff}' \
|
67
|
+
']'
|
68
|
+
)
|
69
|
+
|
70
|
+
# Translate well-known entities, or use generic unicode hex entity
|
71
|
+
DISCOURAGED_REPLACEMENTS = Hash.new do |_, c|
|
72
|
+
"&#x#{c.ord.to_s(16)};".freeze
|
73
|
+
end.update(
|
74
|
+
'"'.freeze => '"'.freeze,
|
75
|
+
'&'.freeze => '&'.freeze,
|
76
|
+
"'".freeze => '''.freeze,
|
77
|
+
'<'.freeze => '<'.freeze,
|
78
|
+
'>'.freeze => '>'.freeze
|
79
|
+
).freeze
|
80
|
+
|
81
|
+
def self.escape(text)
|
82
|
+
text.to_s
|
83
|
+
.encode(Encoding::UTF_8)
|
84
|
+
.gsub(ILLEGAL_REGEXP, ILLEGAL_REPLACEMENT)
|
85
|
+
.gsub(DISCOURAGED_REGEXP, DISCOURAGED_REPLACEMENTS)
|
86
|
+
end
|
87
|
+
|
88
|
+
# rubocop:disable Metrics/LineLength
|
89
|
+
STRIP_DIFF_COLORS_BLOCK_REGEXP = /^ ( [ ]* ) Diff: (?: \e\[ 0 m )? (?: \n \1 \e\[ \d+ (?: ; \d+ )* m .* )* /x.freeze
|
90
|
+
# rubocop:enable Metrics/LineLength
|
91
|
+
STRIP_DIFF_COLORS_CODES_REGEXP = /\e\[ \d+ (?: ; \d+ )* m/x.freeze
|
92
|
+
|
93
|
+
def self.strip_diff_colors(string)
|
94
|
+
# XXX: RSpec diffs are appended to the message lines fairly early and will
|
95
|
+
# contain ANSI escape codes for colorizing terminal output if the global
|
96
|
+
# rspec configuration is turned on, regardless of which notification lines
|
97
|
+
# we ask for. We need to strip the codes from the diff part of the message
|
98
|
+
# for XML output here.
|
99
|
+
#
|
100
|
+
# We also only want to target the diff hunks because the failure message
|
101
|
+
# itself might legitimately contain ansi escape codes.
|
102
|
+
#
|
103
|
+
string.sub(STRIP_DIFF_COLORS_BLOCK_REGEXP) do |match|
|
104
|
+
match.gsub(STRIP_DIFF_COLORS_CODES_REGEXP, ''.freeze)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Metrics/ClassLength
|
4
|
+
|
5
|
+
# Formatter for RSpec
|
6
|
+
# Write an file xml for reporting errors.
|
7
|
+
class JUnit < RSpec::Core::Formatters::BaseFormatter
|
8
|
+
RSpec::Core::Formatters.register self,
|
9
|
+
:start,
|
10
|
+
:stop,
|
11
|
+
:dump_summary
|
12
|
+
|
13
|
+
attr_reader :started
|
14
|
+
|
15
|
+
def initialize(output)
|
16
|
+
@output = output
|
17
|
+
end
|
18
|
+
|
19
|
+
def start(notification)
|
20
|
+
@start_notification = notification
|
21
|
+
@started = Time.now
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def stop(notification)
|
26
|
+
@examples_notification = notification
|
27
|
+
end
|
28
|
+
|
29
|
+
def dump_summary(notification)
|
30
|
+
@summary_notification = notification
|
31
|
+
xml = RspecJunitFormatterBitbucket::XML.new(@output, self)
|
32
|
+
|
33
|
+
without_color do
|
34
|
+
xml.dump
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# private
|
39
|
+
|
40
|
+
def example_count
|
41
|
+
@summary_notification.example_count
|
42
|
+
end
|
43
|
+
|
44
|
+
def pending_count
|
45
|
+
@summary_notification.pending_count
|
46
|
+
end
|
47
|
+
|
48
|
+
def failure_count
|
49
|
+
@summary_notification.failure_count
|
50
|
+
end
|
51
|
+
|
52
|
+
def duration
|
53
|
+
@summary_notification.duration
|
54
|
+
end
|
55
|
+
|
56
|
+
def examples
|
57
|
+
@examples_notification.notifications
|
58
|
+
end
|
59
|
+
|
60
|
+
def result_of(notification)
|
61
|
+
notification.example.execution_result.status
|
62
|
+
end
|
63
|
+
|
64
|
+
def failure_type_for(example)
|
65
|
+
exception_for(example).class.name
|
66
|
+
end
|
67
|
+
|
68
|
+
def failure_message_for(example)
|
69
|
+
exception = exception_for(example).to_s
|
70
|
+
RspecJunitFormatterBitbucket::Format.strip_diff_colors(exception)
|
71
|
+
end
|
72
|
+
|
73
|
+
def failure_for(notification)
|
74
|
+
exception = notification.message_lines.join("\n")
|
75
|
+
RspecJunitFormatterBitbucket::Format.strip_diff_colors(exception) << \
|
76
|
+
"\n" << notification.formatted_backtrace.join("\n")
|
77
|
+
end
|
78
|
+
|
79
|
+
def exception_for(notification)
|
80
|
+
notification.example.execution_result.exception
|
81
|
+
end
|
82
|
+
|
83
|
+
# rspec makes it really difficult to swap in configuration temporarily due to
|
84
|
+
# the way it cascades defaults, command line arguments, and user
|
85
|
+
# configuration. This method makes sure configuration gets swapped in
|
86
|
+
# correctly, but also that the original state is definitely restored.
|
87
|
+
def swap_rspec_configuration(key, value)
|
88
|
+
unset = Object.new
|
89
|
+
force = RSpec.configuration.send(:value_for, key) { unset }
|
90
|
+
previous = check_swap(key, value, force, unset)
|
91
|
+
yield
|
92
|
+
ensure
|
93
|
+
ensure_swap(key, force, previous, unset)
|
94
|
+
end
|
95
|
+
|
96
|
+
def check_swap(key, value, force, unset)
|
97
|
+
if unset.equal?(force)
|
98
|
+
previous = RSpec.configuration.send(key)
|
99
|
+
RSpec.configuration.send(:"#{key}=", value)
|
100
|
+
else
|
101
|
+
RSpec.configuration.force(key => value)
|
102
|
+
end
|
103
|
+
previous
|
104
|
+
end
|
105
|
+
|
106
|
+
def ensure_swap(key, force, previous, unset)
|
107
|
+
if unset.equal?(force)
|
108
|
+
RSpec.configuration.send(:"#{key}=", previous)
|
109
|
+
else
|
110
|
+
RSpec.configuration.force(key => force)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Completely gross hack for absolutely forcing off colorising for the
|
115
|
+
# duration of a block.
|
116
|
+
if RSpec.configuration.respond_to?(:color_mode=)
|
117
|
+
def without_color(&block)
|
118
|
+
swap_rspec_configuration(:color_mode, :off, &block)
|
119
|
+
end
|
120
|
+
elsif RSpec.configuration.respond_to?(:color=)
|
121
|
+
def without_color(&block)
|
122
|
+
swap_rspec_configuration(:color, false, &block)
|
123
|
+
end
|
124
|
+
else
|
125
|
+
warn 'rspec_junit_formatter cannot prevent colorising due ' \
|
126
|
+
'to an unexpected RSpec.configuration format'
|
127
|
+
def without_color
|
128
|
+
yield
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def stdout_for(example_notification)
|
133
|
+
example_notification.example.metadata[:stdout]
|
134
|
+
end
|
135
|
+
|
136
|
+
def stderr_for(example_notification)
|
137
|
+
example_notification.example.metadata[:stderr]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
# rubocop:enable Metrics/ClassLength
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Metrics/LineLength
|
4
|
+
module RspecJunitFormatterBitbucket
|
5
|
+
# Write XML file
|
6
|
+
class XML
|
7
|
+
def initialize(output, example)
|
8
|
+
@test = example
|
9
|
+
@output = output
|
10
|
+
@output << first_node
|
11
|
+
end
|
12
|
+
|
13
|
+
def dump
|
14
|
+
@output << %(<test-suite #{testsuite_attr} >\n)
|
15
|
+
@output << %(<properties>\n)
|
16
|
+
@output << %(<property)
|
17
|
+
@output << %( name="seed")
|
18
|
+
@output << %( value="#{Format.escape(RSpec.configuration.seed.to_s)}")
|
19
|
+
@output << %(/>\n)
|
20
|
+
@output << %(</properties>\n)
|
21
|
+
dump_examples
|
22
|
+
@output << %(</test-suite>\n)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def first_node
|
28
|
+
%(<?xml version="1.0" encoding="UTF-8"?>\n\n)
|
29
|
+
end
|
30
|
+
|
31
|
+
def testsuite_attr
|
32
|
+
<<~TESTSUITE
|
33
|
+
name="rspec#{Format.escape(ENV['TEST_ENV_NUMBER'].to_s)}"
|
34
|
+
tests="#{@test.example_count}"
|
35
|
+
skipped="#{@test.pending_count}"
|
36
|
+
failures="#{@test.failure_count}"
|
37
|
+
errors="0"
|
38
|
+
time="#{Format.escape(format('%.6f', @test.duration))}"
|
39
|
+
timestamp="#{Format.escape(@test.started.iso8601)}"
|
40
|
+
hostname="#{Format.escape(Socket.gethostname)}"
|
41
|
+
TESTSUITE
|
42
|
+
end
|
43
|
+
|
44
|
+
def dump_examples
|
45
|
+
@test.examples.each do |example|
|
46
|
+
case @test.result_of(example)
|
47
|
+
when :pending
|
48
|
+
dump_pending(example)
|
49
|
+
when :failed
|
50
|
+
dump_failed(example)
|
51
|
+
else
|
52
|
+
dump_example(example)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def dump_pending(example)
|
58
|
+
dump_example(example) do
|
59
|
+
@output << %(<skipped/>)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def dump_failed(example)
|
64
|
+
dump_example(example) do
|
65
|
+
@output << %(<failure)
|
66
|
+
@output << %( message="#{Format.escape(@test.failure_message_for(example))}")
|
67
|
+
@output << %( type="#{Format.escape(@test.failure_type_for(example))}")
|
68
|
+
@output << %(>)
|
69
|
+
@output << Format.escape(@test.failure_for(example))
|
70
|
+
@output << %(</failure>)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def dump_example(example)
|
75
|
+
@output << %(<test-case )
|
76
|
+
@output << testcase_attr(example)
|
77
|
+
@output << %(>)
|
78
|
+
yield if block_given?
|
79
|
+
dump_output(example)
|
80
|
+
@output << %(</test-case>\n)
|
81
|
+
end
|
82
|
+
|
83
|
+
def testcase_attr(example)
|
84
|
+
<<~TESTCASE
|
85
|
+
classname="#{Format.escape(Attribute.classname_for(example))}"
|
86
|
+
name="#{Format.escape(Attribute.description_for(example))}"
|
87
|
+
file="#{Format.escape(Attribute.example_group_file_path_for(example))}"
|
88
|
+
time="#{Format.escape(format('%.6f', Attribute.duration_for(example)))}"
|
89
|
+
TESTCASE
|
90
|
+
end
|
91
|
+
|
92
|
+
def dump_output(example)
|
93
|
+
stdout = @test.stdout_for(example)
|
94
|
+
write_stdout(stdout) unless stdout.empty?
|
95
|
+
|
96
|
+
stderr = @test.stderr_for(example)
|
97
|
+
write_stderr(stderr) unless stderr.empty?
|
98
|
+
end
|
99
|
+
|
100
|
+
def write_stdout(stdout)
|
101
|
+
@output << %(<system-out>)
|
102
|
+
@output << Format.escape(stdout)
|
103
|
+
@output << %(</system-out>)
|
104
|
+
end
|
105
|
+
|
106
|
+
def write_stderr(stderr)
|
107
|
+
@output << %(<system-err>)
|
108
|
+
@output << Format.escape(stderr)
|
109
|
+
@output << %(</system-err>)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
# rubocop:enable Metrics/LineLength
|
@@ -6,15 +6,7 @@ require 'time'
|
|
6
6
|
require 'rspec/core'
|
7
7
|
require 'rspec/core/formatters/base_formatter'
|
8
8
|
|
9
|
-
require 'rspec_junit_formatter_bitbucket/
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
9
|
+
require 'rspec_junit_formatter_bitbucket/attribute'
|
10
|
+
require 'rspec_junit_formatter_bitbucket/format'
|
11
|
+
require 'rspec_junit_formatter_bitbucket/xml'
|
12
|
+
require 'rspec_junit_formatter_bitbucket/j_unit'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec_junit_formatter_bitbucket
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0.pre.170
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- VAILLANT Jeremy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-05-
|
11
|
+
date: 2019-05-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-core
|
@@ -36,6 +36,20 @@ dependencies:
|
|
36
36
|
- - "<"
|
37
37
|
- !ruby/object:Gem::Version
|
38
38
|
version: '4'
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: appraisal
|
41
|
+
requirement: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - "~>"
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '2.2'
|
46
|
+
type: :development
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - "~>"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '2.2'
|
39
53
|
- !ruby/object:Gem::Dependency
|
40
54
|
name: bundler
|
41
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -57,19 +71,25 @@ dependencies:
|
|
57
71
|
- !ruby/object:Gem::Version
|
58
72
|
version: 1.17.3
|
59
73
|
- !ruby/object:Gem::Dependency
|
60
|
-
name:
|
74
|
+
name: coderay
|
61
75
|
requirement: !ruby/object:Gem::Requirement
|
62
76
|
requirements:
|
63
77
|
- - "~>"
|
64
78
|
- !ruby/object:Gem::Version
|
65
|
-
version: '
|
79
|
+
version: '1.1'
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.1.2
|
66
83
|
type: :development
|
67
84
|
prerelease: false
|
68
85
|
version_requirements: !ruby/object:Gem::Requirement
|
69
86
|
requirements:
|
70
87
|
- - "~>"
|
71
88
|
- !ruby/object:Gem::Version
|
72
|
-
version: '
|
89
|
+
version: '1.1'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 1.1.2
|
73
93
|
- !ruby/object:Gem::Dependency
|
74
94
|
name: nokogiri
|
75
95
|
requirement: !ruby/object:Gem::Requirement
|
@@ -90,6 +110,20 @@ dependencies:
|
|
90
110
|
- - ">="
|
91
111
|
- !ruby/object:Gem::Version
|
92
112
|
version: 1.8.2
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: pry
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: 0.12.2
|
120
|
+
type: :development
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - "~>"
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: 0.12.2
|
93
127
|
- !ruby/object:Gem::Dependency
|
94
128
|
name: rake
|
95
129
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,39 +145,33 @@ dependencies:
|
|
111
145
|
- !ruby/object:Gem::Version
|
112
146
|
version: 12.3.2
|
113
147
|
- !ruby/object:Gem::Dependency
|
114
|
-
name:
|
148
|
+
name: rubocop
|
115
149
|
requirement: !ruby/object:Gem::Requirement
|
116
150
|
requirements:
|
117
151
|
- - "~>"
|
118
152
|
- !ruby/object:Gem::Version
|
119
|
-
version:
|
120
|
-
- - ">="
|
121
|
-
- !ruby/object:Gem::Version
|
122
|
-
version: 1.1.2
|
153
|
+
version: 0.69.0
|
123
154
|
type: :development
|
124
155
|
prerelease: false
|
125
156
|
version_requirements: !ruby/object:Gem::Requirement
|
126
157
|
requirements:
|
127
158
|
- - "~>"
|
128
159
|
- !ruby/object:Gem::Version
|
129
|
-
version:
|
130
|
-
- - ">="
|
131
|
-
- !ruby/object:Gem::Version
|
132
|
-
version: 1.1.2
|
160
|
+
version: 0.69.0
|
133
161
|
- !ruby/object:Gem::Dependency
|
134
|
-
name:
|
162
|
+
name: rubocop-rspec
|
135
163
|
requirement: !ruby/object:Gem::Requirement
|
136
164
|
requirements:
|
137
165
|
- - "~>"
|
138
166
|
- !ruby/object:Gem::Version
|
139
|
-
version:
|
167
|
+
version: '1.33'
|
140
168
|
type: :development
|
141
169
|
prerelease: false
|
142
170
|
version_requirements: !ruby/object:Gem::Requirement
|
143
171
|
requirements:
|
144
172
|
- - "~>"
|
145
173
|
- !ruby/object:Gem::Version
|
146
|
-
version:
|
174
|
+
version: '1.33'
|
147
175
|
description: |2
|
148
176
|
RSpec Junit Formatter results that your CI can read in Bitbucket Pipeline.
|
149
177
|
Use convention http://reflex.gforge.inria.fr
|
@@ -156,8 +184,11 @@ files:
|
|
156
184
|
- LICENSE
|
157
185
|
- README.md
|
158
186
|
- lib/rspec_junit_formatter_bitbucket.rb
|
187
|
+
- lib/rspec_junit_formatter_bitbucket/attribute.rb
|
188
|
+
- lib/rspec_junit_formatter_bitbucket/format.rb
|
159
189
|
- lib/rspec_junit_formatter_bitbucket/info.rb
|
160
|
-
- lib/rspec_junit_formatter_bitbucket/
|
190
|
+
- lib/rspec_junit_formatter_bitbucket/j_unit.rb
|
191
|
+
- lib/rspec_junit_formatter_bitbucket/xml.rb
|
161
192
|
homepage: https://github.com/dazzl-tv/rspec_junit_formatter
|
162
193
|
licenses:
|
163
194
|
- MIT
|
@@ -170,7 +201,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
170
201
|
requirements:
|
171
202
|
- - ">="
|
172
203
|
- !ruby/object:Gem::Version
|
173
|
-
version: 2.
|
204
|
+
version: 2.4.0
|
174
205
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
206
|
requirements:
|
176
207
|
- - ">="
|
@@ -1,355 +0,0 @@
|
|
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
|