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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 406b38492456241386e52eba83fca1ae1fe3835be224415ffc7d465d5ab5dba0
4
- data.tar.gz: 9c7b748c2d2b70a17cec376f65beb996164306926653d86a4e815fce93e8f443
3
+ metadata.gz: da625be220376cea7a09f0c1870b2bea24b5f40e825a8c7296ed76318ecf1cff
4
+ data.tar.gz: c9ae2324d2e151ee747eebd08ffa7245bec2860414392d44731a3234e4d0f797
5
5
  SHA512:
6
- metadata.gz: 2ac815d3b5d2aa7b58a73c5fec13f1675d24277663998bf3da4c07bf7ada2bd6b3b206f6693b33951ed0a81b32889e2baadfe116753459ca712632ae3d29083f
7
- data.tar.gz: 6788c28e17df99db6475ebdb4cf8dfd2072ddd3c85499fdd22a1c1356393876698c6f917d709eb1f67ed27556d5427ca991f9e503ddb32bcb803c686ccd991b4
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 | [![Build Status](https://travis-ci.org/dazzl-tv/rspec_junit_formatter.svg?branch=master)](https://travis-ci.org/dazzl-tv/rspec_junit_formatter) [![Gem Version](https://badge.fury.io/rb/rspec_junit_formatter_bitbucket.svg)](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
- [![Build results](http://img.shields.io/travis/sj26/rspec_junit_formatter/master.svg)](https://travis-ci.org/sj26/rspec_junit_formatter)
8
- [![Gem version](http://img.shields.io/gem/v/rspec_junit_formatter.svg)](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 rspec_junit_formatter
14
+ gem install rspec_junit_formatter_bitbucket
23
15
  ```
24
16
 
25
17
  Use it:
26
18
 
27
19
  ```sh
28
- rspec --format RspecJunitFormatter --out rspec.xml
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 `rspec.xml` with your results in it.
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 RspecJunitFormatter --out rspec.xml
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-6/docs/formatters
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 "rspec_junit_formatter"
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 RspecJunitFormatter
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
- 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
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 => '&quot;'.freeze,
75
+ '&'.freeze => '&amp;'.freeze,
76
+ "'".freeze => '&apos;'.freeze,
77
+ '<'.freeze => '&lt;'.freeze,
78
+ '>'.freeze => '&gt;'.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
@@ -4,7 +4,7 @@
4
4
  module RspecJunitFormatterBitbucket
5
5
  module Info
6
6
  # Define version
7
- VERSION = '0.1.0'
7
+ VERSION = '0.2.0'
8
8
 
9
9
  # Define Name
10
10
  GEM_NAME = 'rspec_junit_formatter_bitbucket'
@@ -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/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
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.1.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-20 00:00:00.000000000 Z
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: appraisal
74
+ name: coderay
61
75
  requirement: !ruby/object:Gem::Requirement
62
76
  requirements:
63
77
  - - "~>"
64
78
  - !ruby/object:Gem::Version
65
- version: '2.2'
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: '2.2'
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: coderay
148
+ name: rubocop
115
149
  requirement: !ruby/object:Gem::Requirement
116
150
  requirements:
117
151
  - - "~>"
118
152
  - !ruby/object:Gem::Version
119
- version: '1.1'
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: '1.1'
130
- - - ">="
131
- - !ruby/object:Gem::Version
132
- version: 1.1.2
160
+ version: 0.69.0
133
161
  - !ruby/object:Gem::Dependency
134
- name: pry
162
+ name: rubocop-rspec
135
163
  requirement: !ruby/object:Gem::Requirement
136
164
  requirements:
137
165
  - - "~>"
138
166
  - !ruby/object:Gem::Version
139
- version: 0.12.2
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: 0.12.2
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/init.rb
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.0.0
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 => '&quot;'.freeze,
306
- '&'.freeze => '&amp;'.freeze,
307
- "'".freeze => '&apos;'.freeze,
308
- '<'.freeze => '&lt;'.freeze,
309
- '>'.freeze => '&gt;'.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