what_weve_got_here_is_an_error_to_communicate 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +4 -0
  4. data/.travis.yml +7 -0
  5. data/Gemfile +2 -0
  6. data/Rakefile +6 -0
  7. data/Readme.md +34 -0
  8. data/acceptance +29 -0
  9. data/experiments/formatting/5_potential_structure_dsls.rb +88 -0
  10. data/experiments/formatting/half_thoughtout_dsl_for_toplevel_structure_of_argument_error.rb +43 -0
  11. data/experiments/formatting/haml_like_structure.rb +139 -0
  12. data/experiments/formatting/other_structures +156 -0
  13. data/lib/error_to_communicate.rb +3 -0
  14. data/lib/error_to_communicate/at_exit.rb +11 -0
  15. data/lib/error_to_communicate/config.rb +32 -0
  16. data/lib/error_to_communicate/exception_info.rb +41 -0
  17. data/lib/error_to_communicate/format.rb +132 -0
  18. data/lib/error_to_communicate/format/terminal_helpers.rb +97 -0
  19. data/lib/error_to_communicate/parse/backtrace.rb +34 -0
  20. data/lib/error_to_communicate/parse/exception.rb +21 -0
  21. data/lib/error_to_communicate/parse/no_method_error.rb +27 -0
  22. data/lib/error_to_communicate/parse/registry.rb +30 -0
  23. data/lib/error_to_communicate/parse/wrong_number_of_arguments.rb +35 -0
  24. data/lib/error_to_communicate/rspec_formatter.rb +46 -0
  25. data/lib/error_to_communicate/version.rb +3 -0
  26. data/lib/what_weve_got_here_is_an_error_to_communicate.rb +3 -0
  27. data/screenshot.png +0 -0
  28. data/spec/acceptance/argument_error_spec.rb +55 -0
  29. data/spec/acceptance/exception_spec.rb +29 -0
  30. data/spec/acceptance/no_error_spec.rb +44 -0
  31. data/spec/acceptance/no_methood_error_spec.rb +50 -0
  32. data/spec/acceptance/spec_helper.rb +41 -0
  33. data/spec/parse/backtrace_spec.rb +101 -0
  34. data/spec/parse/exception_spec.rb +14 -0
  35. data/spec/parse/no_method_error_spec.rb +23 -0
  36. data/spec/parse/registered_parsers_spec.rb +68 -0
  37. data/spec/parse/spec_helper.rb +23 -0
  38. data/spec/parse/wrong_number_of_arguments_spec.rb +77 -0
  39. data/spec/rspec_formatter_spec.rb +95 -0
  40. data/spec/spec_helper.rb +20 -0
  41. data/what_weve_got_here_is_an_error_to_communicate.gemspec +19 -0
  42. metadata +168 -0
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.shared_examples 'an exception parser' do |attributes|
4
+ let(:message) { attributes.fetch :sample_message }
5
+ let(:explanation) { attributes.fetch :sample_explanation, message }
6
+
7
+ let :exception do
8
+ FakeException.new message: message,
9
+ backtrace: ["/Users/someone/a/b/c.rb:123:in `some_method_name'"]
10
+ end
11
+
12
+ it 'records the exception, class name, and explanation comes from the message' do
13
+ info = parse exception
14
+ expect(info.exception ).to equal exception
15
+ expect(info.classname ).to eq 'FakeException'
16
+ expect(info.explanation).to eq explanation
17
+ end
18
+
19
+ it 'records the backtrace locations' do
20
+ info = parse exception
21
+ expect(info.backtrace.map &:linenum).to eq [123]
22
+ end
23
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+ require 'parse/spec_helper'
3
+ require 'error_to_communicate/parse/wrong_number_of_arguments'
4
+
5
+ RSpec.describe 'parsing wrong number of arguments', parse: true do
6
+ def parse(exception)
7
+ WhatWeveGotHereIsAnErrorToCommunicate::Parse::WrongNumberOfArguments.parse(exception)
8
+ end
9
+
10
+ it_behaves_like 'an exception parser',
11
+ sample_message: "wrong number of arguments (1 for 0) (ArgumentError)",
12
+ sample_explanation: "Wrong number of arguments"
13
+
14
+ describe 'parse?' do
15
+ def will_parse?(exception)
16
+ WhatWeveGotHereIsAnErrorToCommunicate::Parse::WrongNumberOfArguments.parse?(exception)
17
+ end
18
+
19
+ def will_parse!(exception)
20
+ expect(will_parse? exception).to be_truthy
21
+ end
22
+
23
+ def wont_parse!(exception)
24
+ expect(will_parse? exception).to be_falsy
25
+ end
26
+
27
+ it 'is true when given an MRI style wrong number of arguments message' do
28
+ will_parse! ArgumentError.new "wrong number of arguments (1 for 0)"
29
+ end
30
+
31
+ it 'is true when given an RBX style wrong number of arguments message' do
32
+ will_parse! ArgumentError.new "method 'a': given 1, expected 0"
33
+ end
34
+
35
+ it 'is true when given an JRuby style wrong number of arguments message' do
36
+ will_parse! ArgumentError.new "wrong number of arguments calling `a` (1 for 0)"
37
+ end
38
+
39
+ it 'is true when given an MRI style wrong number of arguments message' do
40
+ will_parse! ArgumentError.new "wrong number of arguments (1 for 0)"
41
+ end
42
+
43
+ it 'is false for ArgumentErrors that are not "wrong number of arguments"' do
44
+ wont_parse! ArgumentError.new "Some other kind of ArgumentError"
45
+ end
46
+
47
+ it 'is false when the message is contained within some other message (not overeager)' do
48
+ wont_parse! RSpec::Expectations::ExpectationNotMetError.new(<<-MESSAGE)
49
+ expected: "wrong number of arguments (1 for 0) (ArgumentError)"
50
+ got: "Wrong number of arguments"
51
+
52
+ (compared using ==)
53
+ MESSAGE
54
+ end
55
+ end
56
+
57
+ describe 'parse' do
58
+ let(:mri_message) { "wrong number of arguments (1 for 0)" }
59
+ let(:mri_parsed) { parse FakeException.new(message: mri_message) }
60
+
61
+ let(:rbx_message) { "method 'a': given 1, expected 0" }
62
+ let(:rbx_parsed) { parse FakeException.new(message: rbx_message) }
63
+
64
+ let(:jruby_message) { "wrong number of arguments calling `a` (1 for 0)" }
65
+ let(:jruby_parsed) { parse FakeException.new(message: "wrong number of arguments calling `a` (1 for 0)") }
66
+
67
+ it 'extracts the number of arguments that were passed' do
68
+ expect(rbx_parsed.num_expected).to eq 0
69
+ expect(mri_parsed.num_expected).to eq 0
70
+ end
71
+
72
+ it 'extracts the number of arguments that were received' do
73
+ expect(rbx_parsed.num_received).to eq 1
74
+ expect(mri_parsed.num_received).to eq 1
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,95 @@
1
+ require 'stringio'
2
+ require 'spec_helper'
3
+
4
+ RSpec.describe ErrorToCommunicate::RSpecFormatter, formatter: true do
5
+ let(:substring_that_would_only_be_in_full_backtrace) { 'lib/rspec/core' }
6
+
7
+ def formatter_for(attributes)
8
+ outstream = attributes.fetch(:outstream) { StringIO.new }
9
+ described_class.new(outstream)
10
+ end
11
+
12
+ def new_formatter
13
+ formatter_for({})
14
+ end
15
+
16
+ # The interfaces mocked out here were taken from RSpec 3.2.2
17
+ # They're all private, but IDK how else to test it :/
18
+ def run_specs_against(formatter, *describe_args, &describe_block)
19
+ # Create the example group
20
+ # define some methods to decouple it from the global test suite
21
+ group = RSpec::Core::ExampleGroup.describe(*describe_args, &describe_block)
22
+ class << group
23
+ alias filtered_examples examples
24
+ def fail_fast?() false end
25
+ end
26
+
27
+ # The reporter calls into our formatter
28
+ reporter = RSpec::Core::Reporter.new(RSpec::Core::Configuration.new)
29
+
30
+ # Register the formatter for all notifications it would actually receive
31
+ registered_notifications = formatter.class.ancestors.flat_map do |ancestor|
32
+ RSpec::Core::Formatters::Loader.formatters.fetch(ancestor, [])
33
+ end
34
+ registered_notifications.each do |notification|
35
+ reporter.register_listener formatter, notification
36
+ end
37
+
38
+ # Fake out the runner
39
+ # ordering comes from: http://rspec.info/documentation/3.2/rspec-core/RSpec/Core/Formatters.html
40
+ reporter.start(expected_example_count=123)
41
+ group.run(reporter)
42
+ reporter.finish
43
+ end
44
+
45
+ def this_line_of_code
46
+ file, line = caller[0].split(":").take(2)
47
+ File.read(file).lines[line.to_i].strip
48
+ end
49
+
50
+ def get_printed(formatter)
51
+ # FIXME: hack until we get it respecting colour on/off
52
+ formatter.output.string.gsub(/\e\[\d+(;\d+)*?m/, '')
53
+ end
54
+
55
+ it 'uses our lib to print the details of failing examples.' do
56
+ formatter = new_formatter
57
+ context_around_failure = this_line_of_code
58
+ run_specs_against formatter do
59
+ example('will fail') { fail }
60
+ end
61
+ expect(get_printed formatter).to include context_around_failure
62
+
63
+ formatter = new_formatter
64
+ context_around_success = this_line_of_code
65
+ run_specs_against formatter do
66
+ example('will pass') { }
67
+ end
68
+ expect(get_printed formatter).to_not include context_around_success
69
+ end
70
+
71
+ it 'numbers the failure and prints the failure descriptions' do
72
+ formatter = new_formatter
73
+ run_specs_against formatter, 'GroupName' do
74
+ example('hello') { fail }
75
+ example('world') { fail }
76
+ end
77
+ expect(get_printed formatter).to match /1\)\s*GroupName\s*hello/
78
+ expect(get_printed formatter).to match /2\)\s*GroupName\s*world/
79
+ end
80
+
81
+ it 'respects the backtrace formatter (ie the --backtrace flag)' do
82
+ # only need to check a failing example to show it uses RSpec's backtrace formatter
83
+ formatter = new_formatter
84
+ run_specs_against(formatter) { example { fail } }
85
+ expect(get_printed formatter)
86
+ .to_not include substring_that_would_only_be_in_full_backtrace
87
+ end
88
+
89
+ it 'respects colour enabling/disabling' do
90
+ # https://github.com/rspec/rspec-core/blob/2a07aa92560cf6d4ae73ab04ff3b9b565451e83f/spec/rspec/core/formatters/console_codes_spec.rb#L35
91
+ # allow(RSpec.configuration).to receive(:color_enabled?) { true }
92
+ pending 'We don\'t yet have the ability to turn color printing on/off'
93
+ fail
94
+ end
95
+ end
@@ -0,0 +1,20 @@
1
+ class FakeException
2
+ attr_reader :message, :backtrace
3
+
4
+ def initialize(attributes)
5
+ @message = attributes.fetch :message, 'default message'
6
+ @backtrace = attributes.fetch(:backtrace, [])
7
+ end
8
+
9
+ def exception
10
+ self
11
+ end
12
+ end
13
+
14
+ RSpec.configure do |config|
15
+ # Stop testing after first failure
16
+ config.fail_fast = true
17
+
18
+ # Don't define should/describe on Object
19
+ config.disable_monkey_patching!
20
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'lib/error_to_communicate/version'
2
+ Gem::Specification.new do |s|
3
+ s.name = 'what_weve_got_here_is_an_error_to_communicate'
4
+ s.version = WhatWeveGotHereIsAnErrorToCommunicate::VERSION
5
+ s.licenses = ['MIT']
6
+ s.summary = "Readable, helpful error messages"
7
+ s.description = "Hooks into program lifecycle to display error messages to you in a helpufl way, with inlined code, colour, and helpful heuristics about what might be the cause."
8
+ s.authors = ["Josh Cheek", "Ben Voss"]
9
+ s.email = 'josh.cheek@gmail.com'
10
+ s.files = `git ls-files`.split("\n")
11
+ s.homepage = 'https://github.com/JoshCheek/what-we-ve-got-here-is-an-error-to-communicate'
12
+
13
+ s.add_runtime_dependency 'coderay', '~> 1.1'
14
+
15
+ s.add_development_dependency 'rspec', '~> 3.2'
16
+ s.add_development_dependency 'haiti', '< 0.3', '>= 0.2.0'
17
+ s.add_development_dependency 'pry', '< 0.11', '>= 0.10.0'
18
+ s.add_development_dependency 'rake', '~> 10.4'
19
+ end
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: what_weve_got_here_is_an_error_to_communicate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Josh Cheek
8
+ - Ben Voss
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-04-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: coderay
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.1'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.1'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rspec
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '3.2'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '3.2'
42
+ - !ruby/object:Gem::Dependency
43
+ name: haiti
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "<"
47
+ - !ruby/object:Gem::Version
48
+ version: '0.3'
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: 0.2.0
52
+ type: :development
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - "<"
57
+ - !ruby/object:Gem::Version
58
+ version: '0.3'
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.2.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: pry
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "<"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.11'
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 0.10.0
72
+ type: :development
73
+ prerelease: false
74
+ version_requirements: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - "<"
77
+ - !ruby/object:Gem::Version
78
+ version: '0.11'
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 0.10.0
82
+ - !ruby/object:Gem::Dependency
83
+ name: rake
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '10.4'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '10.4'
96
+ description: Hooks into program lifecycle to display error messages to you in a helpufl
97
+ way, with inlined code, colour, and helpful heuristics about what might be the cause.
98
+ email: josh.cheek@gmail.com
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - ".gitignore"
104
+ - ".rspec"
105
+ - ".travis.yml"
106
+ - Gemfile
107
+ - Rakefile
108
+ - Readme.md
109
+ - acceptance
110
+ - experiments/formatting/5_potential_structure_dsls.rb
111
+ - experiments/formatting/half_thoughtout_dsl_for_toplevel_structure_of_argument_error.rb
112
+ - experiments/formatting/haml_like_structure.rb
113
+ - experiments/formatting/other_structures
114
+ - lib/error_to_communicate.rb
115
+ - lib/error_to_communicate/at_exit.rb
116
+ - lib/error_to_communicate/config.rb
117
+ - lib/error_to_communicate/exception_info.rb
118
+ - lib/error_to_communicate/format.rb
119
+ - lib/error_to_communicate/format/terminal_helpers.rb
120
+ - lib/error_to_communicate/parse/backtrace.rb
121
+ - lib/error_to_communicate/parse/exception.rb
122
+ - lib/error_to_communicate/parse/no_method_error.rb
123
+ - lib/error_to_communicate/parse/registry.rb
124
+ - lib/error_to_communicate/parse/wrong_number_of_arguments.rb
125
+ - lib/error_to_communicate/rspec_formatter.rb
126
+ - lib/error_to_communicate/version.rb
127
+ - lib/what_weve_got_here_is_an_error_to_communicate.rb
128
+ - screenshot.png
129
+ - spec/acceptance/argument_error_spec.rb
130
+ - spec/acceptance/exception_spec.rb
131
+ - spec/acceptance/no_error_spec.rb
132
+ - spec/acceptance/no_methood_error_spec.rb
133
+ - spec/acceptance/spec_helper.rb
134
+ - spec/parse/backtrace_spec.rb
135
+ - spec/parse/exception_spec.rb
136
+ - spec/parse/no_method_error_spec.rb
137
+ - spec/parse/registered_parsers_spec.rb
138
+ - spec/parse/spec_helper.rb
139
+ - spec/parse/wrong_number_of_arguments_spec.rb
140
+ - spec/rspec_formatter_spec.rb
141
+ - spec/spec_helper.rb
142
+ - what_weve_got_here_is_an_error_to_communicate.gemspec
143
+ homepage: https://github.com/JoshCheek/what-we-ve-got-here-is-an-error-to-communicate
144
+ licenses:
145
+ - MIT
146
+ metadata: {}
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 2.4.1
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: Readable, helpful error messages
167
+ test_files: []
168
+ has_rdoc: