├── .gitignore ├── .rspec ├── .travis.yml ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── dictionaries ├── humanist_errors.en.yml └── humanist_errors.oops.yml ├── humanist-errors.gemspec ├── lib ├── humanist_errors.rb └── humanist_errors │ ├── color.rb │ ├── error_mapper.rb │ ├── exception_extensions.rb │ ├── monkey.rb │ ├── regex_hash.rb │ ├── search.rb │ └── version.rb └── test ├── backlog ├── argument_error_test.rb ├── eof_error_test.rb ├── fatal_test.rb ├── float_domain_error_test.rb ├── index_error_test.rb ├── interrupt_test.rb ├── io_error_test.rb ├── key_error_test.rb ├── load_error_test.rb ├── local_jump_error_test.rb ├── name_error_test.rb ├── no_method_error_test.rb ├── not_implemented_error_test.rb ├── range_error_test.rb ├── runtime_error_test.rb ├── script_error_test.rb ├── security_error_test.rb ├── signal_exception_test.rb ├── standard_error_test.rb ├── system_call_error_test.rb ├── system_exit_test.rb ├── system_stack_error_test.rb ├── thread_error_test.rb └── zero_division_error_test.rb ├── color_test.rb ├── error_mapper ├── load_error_test.rb ├── name_error_test.rb ├── no_method_error_test.rb ├── syntax_error_test.rb └── zero_division_error_test.rb ├── features └── syntax_error_test.rb ├── monkey_test.rb ├── regex_hash_test.rb ├── search_test.rb └── test_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.bundle 11 | *.so 12 | *.o 13 | *.a 14 | mkmf.log 15 | test.log 16 | *.gem 17 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format progress 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.2.0 4 | addons: 5 | code_climate: 6 | repo_token: b3ea029e2889a7a6b29cc318cc35e3489be33f0d9d2d97f5b88dee1eaa137695 7 | 8 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | 5 | group :test do 6 | gem 'minitest', require: nil 7 | gem 'minitest-emoji', require: nil 8 | gem 'minitest-focus', require: nil 9 | gem "codeclimate-test-reporter", require: nil 10 | gem 'byebug', require: nil 11 | end 12 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 TODO: Write your name 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Code Climate](https://codeclimate.com/github/bgreg/humanist-errors/badges/gpa.svg)](https://codeclimate.com/github/bgreg/humanist-errors)[![Test Coverage](https://codeclimate.com/github/bgreg/humanist-errors/badges/coverage.svg)](https://codeclimate.com/github/bgreg/humanist-errors)[![Build Status](https://travis-ci.org/bgreg/humanist-errors.svg?branch=master)](https://travis-ci.org/bgreg/humanist-errors) 2 | 3 | # Error messages for Humans. 4 | 5 | [![Join the chat at https://gitter.im/bgreg/humanist-errors](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bgreg/humanist-errors?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 6 | 7 | Humanist errors is a system for extending ruby exception messages. It will prepend the standard output with text 8 | defined in the humanist errors dictionary that hopefully explains what is going on a little better. 9 | 10 | Some examples: 11 | 12 | ![img](https://cloud.githubusercontent.com/assets/3711139/11139081/9ed4493a-897f-11e5-8589-79a4e5930c94.png) 13 | ![img](https://cloud.githubusercontent.com/assets/3711139/11139050/3ccefb40-897f-11e5-8024-9062ce4787bf.png) 14 | 15 | 16 | ## Installation 17 | 18 | Add this line to your application's Gemfile: 19 | 20 | gem 'humanist-errors' 21 | 22 | 23 | And then execute: 24 | 25 | $ bundle 26 | 27 | Or install it yourself as: 28 | 29 | $ gem install humanist-errors 30 | 31 | 32 | ## Usage 33 | 34 | You can use humanist errors globally in your project, or only around specific pieces of code. 35 | To use globally: 36 | 37 | Require the library and monkey file 38 | 39 | require 'humanist_errors' 40 | require 'humanist_errors/monkey' 41 | 42 | Thats it! Now when ruby tries to evaluate an error like when you say: `1/0` you will see a new error message. 43 | 44 | 45 | If you only want to see new errors in an isolated area you can include the library and execute 46 | your code inside a special code block. 47 | 48 | 1. Add these require statements to your file: 49 | 50 | `require 'humanist_errors'` 51 | 52 | `require 'humanist_errors/monkey'` 53 | 54 | 2. Include the humanist errors module: 55 | 56 | `include HumanistErrors` 57 | 58 | 3. Then your code in a human block: 59 | ```ruby 60 | with_human_errors do 61 | #.... 62 | end 63 | ``` 64 | 65 | This gem is intended for use in development and test environments only. 66 | 67 | ## Contributing 68 | 69 | 1. Fork it ( https://github.com/bgreg/humanist-errors/fork ) 70 | 2. Create your feature branch (`git checkout -b my-new-feature`) 71 | 3. Commit your changes (`git commit -am 'Add some feature'`) 72 | 4. Push to the branch (`git push origin my-new-feature`) 73 | 5. Create a new Pull Request 74 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "byebug" 3 | test = File.expand_path('../test', __FILE__) 4 | $LOAD_PATH.unshift(test) unless $LOAD_PATH.include?(test) 5 | 6 | # require 'logger' 7 | # $logger = Logger.new('test.log') 8 | 9 | task default: :test 10 | 11 | task :test do 12 | Dir.glob([ 13 | './test/*_test.rb', 14 | './test/error_mapper/*_test.rb', 15 | './test/features/*_test.rb' 16 | ]).each do |file| 17 | 18 | require file 19 | end 20 | end 21 | 22 | task :test_error_mapper do 23 | Dir.glob('./test/error_mapper/*_test.rb').each { |file| require file } 24 | end 25 | 26 | task :test_features do 27 | Dir.glob('./test/features/*_test.rb').each { |file| require file } 28 | end 29 | 30 | task :search_test do 31 | require './test/search_test.rb' 32 | end 33 | 34 | task :regex_test do 35 | require './test/regex_hash_test.rb' 36 | end 37 | -------------------------------------------------------------------------------- /dictionaries/humanist_errors.en.yml: -------------------------------------------------------------------------------- 1 | :syntax_error: 2 | :unexpected_semi_colon: "You may have missed an argument and ended this line early with a semicolon." 3 | :open_quote: "It looks like you typed an open quote near the end of the file." 4 | :string_formatter: "% string formatter requires a string argument on the left, and a format argument on the right" 5 | :missing_argument: "You indicated that you wanted to send another argument, but we did not see anything." 6 | :missing_block_closer: "A block was started, but you forgot to add 'end'. Ruby tries to match every `do` with an `end`, but it reached the end of the file and a matching 'end' token was not found. To fix this, review all the 'do..end' pairs." 7 | :t_identifier: "Ok, wow, I'm not sure what is going on here" 8 | 9 | :no_method_error: 10 | :undefined_method_for_nil: "You defined a variable with good intentions, then along the way, something turned it to nil." 11 | 12 | :name_error: 13 | :undefined_word: "You typed a random string that wasn't defined. It is not a method or variable in this class, or its ancestors" 14 | 15 | :zero_division_error: 16 | :divide_by_zero: "Science has not figured out how to divide by zero yet. Damn you science!!!" 17 | 18 | :load_error: 19 | :no_file: "You tried to load a file that doesn't exist - at least, not where you think it is!" 20 | -------------------------------------------------------------------------------- /dictionaries/humanist_errors.oops.yml: -------------------------------------------------------------------------------- 1 | :syntax_error: 2 | :unexpected_semi_colon: "oops" 3 | :open_quote: "oops" 4 | :string_formatter: "oops" 5 | :missing_argument: "oops" 6 | :missing_block_closer: "oops" 7 | 8 | :no_method_error: 9 | :undefined_method_for_nil: "oops" 10 | 11 | :name_error: 12 | :undefined_word: "oops" 13 | 14 | :zero_division_error: 15 | :divide_by_zero: "oops" 16 | -------------------------------------------------------------------------------- /humanist-errors.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'humanist_errors/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "humanist-errors" 8 | spec.version = HumanistErrors::VERSION 9 | spec.authors = ["Greg McGuirk"] 10 | spec.email = ["bgregmc@icloud.com"] 11 | spec.summary = %q{More readable and friendly errors, for humans.} 12 | spec.description = %q{This gem appends a new message to the standard exception message, written from the perspective of a person instead of a complier.} 13 | spec.homepage = "http://github.com/bgreg/humanist-errors" 14 | spec.license = "MIT" 15 | 16 | spec.files = `git ls-files -z`.split("\x0") 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(test|spec|features|error_mapper)/}) 19 | 20 | spec.require_paths = ["lib"] 21 | 22 | spec.required_ruby_version = '>= 2.0.0' 23 | spec.add_development_dependency "bundler", "~> 1.7" 24 | spec.add_development_dependency "rake", "~> 10.0" 25 | end 26 | -------------------------------------------------------------------------------- /lib/humanist_errors.rb: -------------------------------------------------------------------------------- 1 | require 'yaml' 2 | require 'humanist_errors/version' 3 | require 'humanist_errors/exception_extensions' 4 | require 'humanist_errors/regex_hash' 5 | require 'humanist_errors/search' 6 | require 'humanist_errors/color' 7 | 8 | module HumanistErrors 9 | STARTING_TOKEN = "Hi!\n" 10 | ENDING_TOKEN = "Here's the error from Ruby: \n" 11 | MESSAGE_DICTIONARY = YAML.load(File.read(File.expand_path('../../dictionaries/humanist_errors.en.yml', __FILE__))) 12 | 13 | def with_human_errors 14 | require 'humanist_errors/monkey' 15 | yield 16 | end 17 | end 18 | 19 | require 'humanist_errors/error_mapper' 20 | -------------------------------------------------------------------------------- /lib/humanist_errors/color.rb: -------------------------------------------------------------------------------- 1 | module HumanistErrors 2 | class Color 3 | PREFIX = '\033' 4 | POSTFIX = '\033[0m' 5 | COLORS = { 6 | black: '[30m', 7 | red: '[31m', 8 | green: '[32m', 9 | brown: '[33m', 10 | blue: '[34m', 11 | magenta: '[35m', 12 | cyan: '[36m', 13 | gray: '[37m', 14 | } 15 | 16 | def colorize_with(color, text) 17 | "#{PREFIX}#{COLORS[color]}#{text}#{POSTFIX}" 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/humanist_errors/error_mapper.rb: -------------------------------------------------------------------------------- 1 | module HumanistErrors 2 | ERROR_MAPPER = { 3 | syntax_error: HumanistErrors::RegexHash[ 4 | /syntax error, unexpected ';'/ => MESSAGE_DICTIONARY[:syntax_error][:unexpected_semi_colon], 5 | /unterminated string meets end of file/ => MESSAGE_DICTIONARY[:syntax_error][:open_quote], 6 | /unterminated quoted string meets end of file/ => MESSAGE_DICTIONARY[:syntax_error][:string_formatter], 7 | /syntax error, unexpected end-of-input, expecting keyword_end/ => MESSAGE_DICTIONARY[:syntax_error][:missing_block_closer], 8 | /syntax error, unexpected end-of-input/ => MESSAGE_DICTIONARY[:syntax_error][:missing_argument], 9 | /syntax error, unexpected tIDENTIFIER/ => MESSAGE_DICTIONARY[:syntax_error][:t_identifier], 10 | /.*/ => :no_result 11 | ], 12 | no_method_error: HumanistErrors::RegexHash[ 13 | /undefined method `.*' for nil:NilClass/ => MESSAGE_DICTIONARY[:no_method_error][:undefined_method_for_nil], 14 | /.*/ => :no_result 15 | ], 16 | name_error: HumanistErrors::RegexHash[ 17 | /undefined local variable or method `.*'/ => MESSAGE_DICTIONARY[:name_error][:undefined_word], 18 | /.*/ => :no_result 19 | ], 20 | zero_division_error: HumanistErrors::RegexHash[ 21 | /divided by 0/ => MESSAGE_DICTIONARY[:zero_division_error][:divide_by_zero], 22 | /.*/ => :no_result 23 | ], 24 | 25 | load_error: HumanistErrors::RegexHash[ 26 | /no such file to load/ => MESSAGE_DICTIONARY[:load_error][:no_file], 27 | /.*/ => :no_result 28 | ] 29 | } 30 | end 31 | -------------------------------------------------------------------------------- /lib/humanist_errors/exception_extensions.rb: -------------------------------------------------------------------------------- 1 | module HumanistErrors 2 | module ExceptionExtensions 3 | def to_s 4 | error = Search.run(self.class, super) 5 | if :no_result == error 6 | super 7 | else 8 | color = Color.new 9 | "\n\n#{color.colorize_with(:green, STARTING_TOKEN)}" \ 10 | " #{color.colorize_with(:cyan, error)}\n" \ 11 | "#{color.colorize_with(:green, ENDING_TOKEN)}\n" + super 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/humanist_errors/monkey.rb: -------------------------------------------------------------------------------- 1 | ::Exception.__send__(:prepend, HumanistErrors::ExceptionExtensions) 2 | -------------------------------------------------------------------------------- /lib/humanist_errors/regex_hash.rb: -------------------------------------------------------------------------------- 1 | module HumanistErrors 2 | class RegexHash < Hash 3 | def [](value) 4 | detect(-> { :no_result }) do |k,v| 5 | if k =~ value 6 | return v 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/humanist_errors/search.rb: -------------------------------------------------------------------------------- 1 | module HumanistErrors 2 | class Search 3 | 4 | def self.run(error_object, ruby_error_message) 5 | searcher = new(error_object, ruby_error_message) 6 | searcher.find 7 | end 8 | 9 | def initialize(error_object, ruby_error_message) 10 | @error_object = error_object 11 | @ruby_error_message = ruby_error_message 12 | end 13 | 14 | def find 15 | error = keyify(error_object) 16 | return :no_result unless ERROR_MAPPER[error] 17 | ERROR_MAPPER[error][ruby_error_message] 18 | end 19 | 20 | private 21 | 22 | attr_reader :error_object, :ruby_error_message, :found_error 23 | 24 | # turn a CamelCase word into an underscored 25 | # symbol to make it nice for hash keys. 26 | # Basically the same as ActiveSupport#underscore 27 | def keyify(error) 28 | error.to_s 29 | .gsub(/::/, '__') 30 | .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') 31 | .gsub(/([a-z\d])([A-Z])/,'\1_\2') 32 | .tr("-", "_") 33 | .downcase 34 | .to_sym 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/humanist_errors/version.rb: -------------------------------------------------------------------------------- 1 | module HumanistErrors 2 | VERSION = "1.0.4" 3 | end 4 | -------------------------------------------------------------------------------- /test/backlog/argument_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ArgumentErrorTest < Minitest::Test 4 | end 5 | -------------------------------------------------------------------------------- /test/backlog/eof_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class EofErrorTest < Minitest::Test 4 | end 5 | -------------------------------------------------------------------------------- /test/backlog/fatal_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class FatalTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/float_domain_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class FloatDomainTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/index_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class IndexErrorTest < Minitest::Test 4 | end 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/backlog/interrupt_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class InterruptTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/io_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class IoErrorTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/key_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class KeyErrorTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/load_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class LoadErrorTest < Minitest::Test 4 | include HumanistErrorsSupport 5 | end 6 | 7 | -------------------------------------------------------------------------------- /test/backlog/local_jump_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class LocalJumpErrorTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/name_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class NoMethodErrorTest < Minitest::Test 4 | include HumanistErrorsSupport 5 | 6 | def test_message_for_random_undefined_word 7 | # error = assert_raises(NameError) { eval('asdf') } 8 | # expected_message = HumanistErrors::MESSAGE_DICTIONARY[:name_error][:undefined_word] 9 | # assert_message(expected_message, error) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/backlog/no_method_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class NoMethodErrorTest < Minitest::Test 4 | include HumanistErrorsSupport 5 | end 6 | -------------------------------------------------------------------------------- /test/backlog/not_implemented_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class NotImplementedErrorTest < Minitest::Test 4 | include HumanistErrorsSupport 5 | end 6 | -------------------------------------------------------------------------------- /test/backlog/range_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class RangeErrorTest < Minitest::Test 4 | end 5 | -------------------------------------------------------------------------------- /test/backlog/runtime_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class RuntimeErrorTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/script_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ScriptErrorTest < Minitest::Test 4 | end 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/backlog/security_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SecurityErrorTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/signal_exception_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SignalExceptionTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/standard_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class StandardErrorTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/system_call_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SystemCallErrorTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/system_exit_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SystemExitTest < Minitest::Test 4 | end 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/backlog/system_stack_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SystemStackErrorTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/thread_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ThreadErrorTest < Minitest::Test 4 | end 5 | 6 | -------------------------------------------------------------------------------- /test/backlog/zero_division_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ZeroDivisionErrorTest < Minitest::Test 4 | include HumanistErrorsSupport 5 | end 6 | -------------------------------------------------------------------------------- /test/color_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ColorTest < Minitest::Test 4 | def colors 5 | { black: '[30m', 6 | red: '[31m', 7 | green: '[32m', 8 | brown: '[33m', 9 | blue: '[34m', 10 | magenta: '[35m', 11 | cyan: '[36m', 12 | gray: '[37m', } 13 | end 14 | 15 | def colorizer 16 | @colorizer ||= HumanistErrors::Color.new 17 | end 18 | 19 | def test_wraps_given_string_with_color 20 | test_string = "Test" 21 | 22 | colors.each do |color_name, code| 23 | assert_equal( 24 | colorizer.colorize_with(color_name, test_string), 25 | "\\033#{code}#{test_string}\\033[0m") 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/error_mapper/load_error_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class LoadErrorTest < Minitest::Test 4 | include HumanistErrorsSupport 5 | 6 | def test_message_for_missing_file 7 | assert_error_map("no such file to load", :load_error, :no_file) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/error_mapper/name_error_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class NameErrorTest < Minitest::Test 4 | include HumanistErrorsSupport 5 | 6 | def test_message_for_random_undefined_word 7 | assert_error_map("NameError: undefined local variable or method `asdf' for main:Object", 8 | :name_error, :undefined_word) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /test/error_mapper/no_method_error_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class NoMethodErrorTest < Minitest::Test 4 | include HumanistErrorsSupport 5 | 6 | def test_error_mapper_for_no_method_error 7 | assert_error_map("undefined method `nonexistentMethod' for nil:NilClass", 8 | :no_method_error, :undefined_method_for_nil) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /test/error_mapper/syntax_error_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class SyntaxErrorTest < Minitest::Test 4 | include HumanistErrorsSupport 5 | 6 | def test_error_mapper_for_syntax_error 7 | assert_error_map("syntax error, unexpected ';'", :syntax_error, :unexpected_semi_colon) 8 | end 9 | 10 | def test_message_for_unterminated_string_meets_end_of_file 11 | assert_error_map("unterminated string meets end of file", :syntax_error, :open_quote) 12 | end 13 | 14 | def test_message_for_single_percent_sign 15 | assert_error_map("unterminated quoted string meets end of file", :syntax_error, :string_formatter) 16 | end 17 | 18 | def test_message_for_missing_block_closer 19 | assert_error_map( 20 | 'syntax error, unexpected end-of-input, expecting keyword_end', 21 | :syntax_error, 22 | :missing_block_closer) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /test/error_mapper/zero_division_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ZeroDivisionErrorTest < Minitest::Test 4 | include HumanistErrorsSupport 5 | 6 | def test_message_for_divide_by_zero 7 | assert_error_map("ZeroDivisionError: divided by 0", :zero_division_error, :divide_by_zero) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/features/syntax_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SyntaxErrorTest < Minitest::Test 4 | def test_message_for_unexpected_semicolon 5 | error_message = human_fork(SyntaxError) { eval('1+;') } 6 | expected_message = HumanistErrors::MESSAGE_DICTIONARY[:syntax_error][:unexpected_semi_colon] 7 | assert_match(expected_message, error_message) 8 | end 9 | 10 | def test_message_for_missing_end 11 | error_message = human_fork(SyntaxError) do 12 | eval( 13 | " def stuff 14 | oops = 'I did it again' 15 | " 16 | ) 17 | end 18 | expected_message = HumanistErrors::MESSAGE_DICTIONARY[:syntax_error][:missing_block_closer] 19 | assert_match(expected_message, error_message) 20 | end 21 | 22 | def test_message_for_unexpected_identifier 23 | error_message = human_fork(SyntaxError) do 24 | eval %q( 25 | one = 1 26 | two = 2 27 | product = one * two _2 28 | ) 29 | end 30 | expected_message = HumanistErrors::MESSAGE_DICTIONARY[:syntax_error][:t_identifier] 31 | assert_match(expected_message, error_message) 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /test/monkey_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class MonkeyTest < Minitest::Test 4 | end 5 | -------------------------------------------------------------------------------- /test/regex_hash_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class RegexHashTest < Minitest::Test 4 | include HumanistErrorsSupport 5 | 6 | def test_a_regex_search_happens_on_key_send 7 | magic_string_hash = HumanistErrors::RegexHash[/findme/ => "hurray!"] 8 | assert_match(magic_string_hash['findme'], "hurray!") 9 | end 10 | 11 | def test_a_failure_when_key_is_not_found 12 | magic_string_hash = HumanistErrors::RegexHash[/findme/ => "hurray!"] 13 | assert_no_result(magic_string_hash['1']) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /test/search_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SearchTest < Minitest::Test 4 | def test_finds_a_human_error 5 | error = HumanistErrors::Search.run( 6 | NameError, 7 | "NameError: undefined local variable or method `asdf' for main:Object" 8 | ) 9 | expected_result = HumanistErrors::MESSAGE_DICTIONARY[:name_error][:undefined_word] 10 | assert(error == expected_result, "#{error.inspect} does not equal: #{expected_result.inspect}") 11 | end 12 | 13 | class DefinitelyNotARealException; end 14 | 15 | def test_cannot_find_a_error_message 16 | error = HumanistErrors::Search.run(DefinitelyNotARealException, "blah blah blah") 17 | assert(error == :no_result, "#{error.inspect} does not equal: :no_result") 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # require "codeclimate-test-reporter" 2 | # CodeClimate::TestReporter.start 3 | 4 | require 'humanist_errors' 5 | require 'humanist_errors/search' 6 | require 'humanist_errors/error_mapper' 7 | require 'minitest/focus' 8 | require 'minitest/emoji' 9 | require 'minitest/autorun' 10 | 11 | module HumanistErrorsSupport 12 | 13 | def assert_result(message) 14 | assert(message != :no_result, "no result was found") 15 | end 16 | 17 | def assert_no_result(message) 18 | assert(message == :no_result, "no result was found") 19 | end 20 | 21 | def assert_error_map(ruby_error, exception_symbol, error_symbol) 22 | result = HumanistErrors::ERROR_MAPPER[exception_symbol][ruby_error] 23 | assert_result(result) 24 | assert_match(result, HumanistErrors::MESSAGE_DICTIONARY[exception_symbol][error_symbol]) 25 | end 26 | 27 | def human_fork(exception) 28 | reader, writer = IO.pipe 29 | 30 | fork do 31 | reader.close 32 | require 'humanist_errors/monkey' 33 | begin 34 | yield 35 | rescue exception => e 36 | writer.puts e.message 37 | end 38 | end 39 | 40 | writer.close 41 | reader.gets(nil) 42 | ensure 43 | reader.close 44 | end 45 | end 46 | --------------------------------------------------------------------------------