did_you_mean 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +48 -0
- data/CHANGELOG.md +75 -75
- data/Gemfile +2 -1
- data/README.md +2 -32
- data/Rakefile +4 -5
- data/appveyor.yml +25 -0
- data/did_you_mean.gemspec +6 -4
- data/documentation/CHANGELOG.md.erb +8 -0
- data/documentation/changelog_generator.rb +34 -0
- data/documentation/human_typo_api.md +20 -0
- data/documentation/tree_spell_algorithm.md +82 -0
- data/documentation/tree_spell_checker_api.md +24 -0
- data/lib/did_you_mean.rb +17 -16
- data/lib/did_you_mean/experimental.rb +2 -2
- data/lib/did_you_mean/experimental/initializer_name_correction.rb +1 -1
- data/lib/did_you_mean/experimental/ivar_name_correction.rb +3 -1
- data/lib/did_you_mean/levenshtein.rb +1 -1
- data/lib/did_you_mean/spell_checker.rb +7 -7
- data/lib/did_you_mean/spell_checkers/key_error_checker.rb +8 -2
- data/lib/did_you_mean/spell_checkers/method_name_checker.rb +14 -6
- data/lib/did_you_mean/spell_checkers/name_error_checkers.rb +2 -2
- data/lib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb +5 -5
- data/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb +1 -1
- data/lib/did_you_mean/tree_spell_checker.rb +137 -0
- data/lib/did_you_mean/verbose.rb +2 -2
- data/lib/did_you_mean/version.rb +1 -1
- data/test/core_ext/test_name_error_extension.rb +48 -0
- data/test/edit_distance/{jaro_winkler_test.rb → test_jaro_winkler.rb} +2 -2
- data/test/fixtures/mini_dir.yml +15 -0
- data/test/fixtures/rspec_dir.yml +112 -0
- data/test/helper.rb +29 -0
- data/test/spell_checking/{class_name_check_test.rb → test_class_name_check.rb} +12 -10
- data/test/spell_checking/{key_name_check_test.rb → test_key_name_check.rb} +18 -8
- data/test/spell_checking/{method_name_check_test.rb → test_method_name_check.rb} +17 -15
- data/test/spell_checking/{uncorrectable_name_check_test.rb → test_uncorrectable_name_check.rb} +3 -3
- data/test/spell_checking/{variable_name_check_test.rb → test_variable_name_check.rb} +18 -16
- data/test/{spell_checker_test.rb → test_spell_checker.rb} +2 -2
- data/test/test_tree_spell_checker.rb +173 -0
- data/test/test_verbose_formatter.rb +21 -0
- data/test/tree_spell/change_word.rb +61 -0
- data/test/tree_spell/human_typo.rb +89 -0
- data/test/tree_spell/test_change_word.rb +38 -0
- data/test/tree_spell/test_explore.rb +128 -0
- data/test/tree_spell/test_human_typo.rb +24 -0
- metadata +47 -58
- data/.travis.yml +0 -23
- data/test/core_ext/name_error_extension_test.rb +0 -51
- data/test/experimental/initializer_name_correction_test.rb +0 -15
- data/test/experimental/method_name_checker_test.rb +0 -13
- data/test/test_helper.rb +0 -13
- data/test/verbose_formatter_test.rb +0 -22
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "../spell_checker"
|
2
2
|
|
3
3
|
module DidYouMean
|
4
4
|
class MethodNameChecker
|
@@ -43,14 +43,22 @@ module DidYouMean
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def corrections
|
46
|
-
@corrections ||= SpellChecker.new(dictionary: RB_RESERVED_WORDS + method_names).correct(method_name) -
|
46
|
+
@corrections ||= SpellChecker.new(dictionary: RB_RESERVED_WORDS + method_names).correct(method_name) - names_to_exclude
|
47
47
|
end
|
48
48
|
|
49
49
|
def method_names
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
if Object === receiver
|
51
|
+
method_names = receiver.methods + receiver.singleton_methods
|
52
|
+
method_names += receiver.private_methods if @private_call
|
53
|
+
method_names.uniq!
|
54
|
+
method_names
|
55
|
+
else
|
56
|
+
[]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def names_to_exclude
|
61
|
+
Object === receiver ? NAMES_TO_EXCLUDE[receiver.class] : []
|
54
62
|
end
|
55
63
|
end
|
56
64
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative 'name_error_checkers/class_name_checker'
|
2
|
+
require_relative 'name_error_checkers/variable_name_checker'
|
3
3
|
|
4
4
|
module DidYouMean
|
5
5
|
class << (NameErrorCheckers = Object.new)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
|
-
|
3
|
-
|
2
|
+
|
3
|
+
require_relative "../../spell_checker"
|
4
4
|
|
5
5
|
module DidYouMean
|
6
6
|
class ClassNameChecker
|
@@ -31,16 +31,16 @@ module DidYouMean
|
|
31
31
|
end.uniq
|
32
32
|
end
|
33
33
|
|
34
|
-
class ClassName <
|
34
|
+
class ClassName < String
|
35
35
|
attr :namespace
|
36
36
|
|
37
37
|
def initialize(name, namespace = '')
|
38
|
-
super(name)
|
38
|
+
super(name.to_s)
|
39
39
|
@namespace = namespace
|
40
40
|
end
|
41
41
|
|
42
42
|
def full_name
|
43
|
-
self.class.new("#{namespace}#{
|
43
|
+
self.class.new("#{namespace}#{self}")
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module DidYouMean
|
2
|
+
# spell checker for a dictionary that has a tree
|
3
|
+
# structure, see doc/tree_spell_checker_api.md
|
4
|
+
class TreeSpellChecker
|
5
|
+
attr_reader :dictionary, :dimensions, :separator, :augment
|
6
|
+
|
7
|
+
def initialize(dictionary:, separator: '/', augment: nil)
|
8
|
+
@dictionary = dictionary
|
9
|
+
@separator = separator
|
10
|
+
@augment = augment
|
11
|
+
@dimensions = parse_dimensions
|
12
|
+
end
|
13
|
+
|
14
|
+
def correct(input)
|
15
|
+
plausibles = plausible_dimensions input
|
16
|
+
return no_idea(input) if plausibles.empty?
|
17
|
+
suggestions = find_suggestions input, plausibles
|
18
|
+
return no_idea(input) if suggestions.empty?
|
19
|
+
suggestions
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def parse_dimensions
|
25
|
+
ParseDimensions.new(dictionary, separator).call
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_suggestions(input, plausibles)
|
29
|
+
states = plausibles[0].product(*plausibles[1..-1])
|
30
|
+
paths = possible_paths states
|
31
|
+
leaf = input.split(separator).last
|
32
|
+
ideas = find_ideas(paths, leaf)
|
33
|
+
ideas.compact.flatten
|
34
|
+
end
|
35
|
+
|
36
|
+
def no_idea(input)
|
37
|
+
return [] unless augment
|
38
|
+
::DidYouMean::SpellChecker.new(dictionary: dictionary).correct(input)
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_ideas(paths, leaf)
|
42
|
+
paths.map do |path|
|
43
|
+
names = find_leaves(path)
|
44
|
+
ideas = CorrectElement.new.call names, leaf
|
45
|
+
ideas_to_paths ideas, leaf, names, path
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def ideas_to_paths(ideas, leaf, names, path)
|
50
|
+
return nil if ideas.empty?
|
51
|
+
return [path + separator + leaf] if names.include? leaf
|
52
|
+
ideas.map { |str| path + separator + str }
|
53
|
+
end
|
54
|
+
|
55
|
+
def find_leaves(path)
|
56
|
+
dictionary.map do |str|
|
57
|
+
next unless str.include? "#{path}#{separator}"
|
58
|
+
str.gsub("#{path}#{separator}", '')
|
59
|
+
end.compact
|
60
|
+
end
|
61
|
+
|
62
|
+
def possible_paths(states)
|
63
|
+
states.map do |state|
|
64
|
+
state.join separator
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def plausible_dimensions(input)
|
69
|
+
elements = input.split(separator)[0..-2]
|
70
|
+
elements.each_with_index.map do |element, i|
|
71
|
+
next if dimensions[i].nil?
|
72
|
+
CorrectElement.new.call dimensions[i], element
|
73
|
+
end.compact
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# parses the elements in each dimension
|
78
|
+
class ParseDimensions
|
79
|
+
def initialize(dictionary, separator)
|
80
|
+
@dictionary = dictionary
|
81
|
+
@separator = separator
|
82
|
+
end
|
83
|
+
|
84
|
+
def call
|
85
|
+
leafless = remove_leaves
|
86
|
+
dimensions = find_elements leafless
|
87
|
+
dimensions.map do |elements|
|
88
|
+
elements.to_set.to_a
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def remove_leaves
|
95
|
+
dictionary.map do |a|
|
96
|
+
elements = a.split(separator)
|
97
|
+
elements[0..-2]
|
98
|
+
end.to_set.to_a
|
99
|
+
end
|
100
|
+
|
101
|
+
def find_elements(leafless)
|
102
|
+
max_elements = leafless.map(&:size).max
|
103
|
+
dimensions = Array.new(max_elements) { [] }
|
104
|
+
(0...max_elements).each do |i|
|
105
|
+
leafless.each do |elements|
|
106
|
+
dimensions[i] << elements[i] unless elements[i].nil?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
dimensions
|
110
|
+
end
|
111
|
+
|
112
|
+
attr_reader :dictionary, :separator
|
113
|
+
end
|
114
|
+
|
115
|
+
# identifies the elements close to element
|
116
|
+
class CorrectElement
|
117
|
+
def initialize
|
118
|
+
end
|
119
|
+
|
120
|
+
def call(names, element)
|
121
|
+
return names if names.size == 1
|
122
|
+
str = normalize element
|
123
|
+
return [str] if names.include? str
|
124
|
+
checker = ::DidYouMean::SpellChecker.new(dictionary: names)
|
125
|
+
checker.correct(str)
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def normalize(leaf)
|
131
|
+
str = leaf.dup
|
132
|
+
str.downcase!
|
133
|
+
return str unless str.include? '@'
|
134
|
+
str.tr!('@', ' ')
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
data/lib/did_you_mean/verbose.rb
CHANGED
data/lib/did_you_mean/version.rb
CHANGED
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
class NameErrorExtensionTest < Test::Unit::TestCase
|
4
|
+
SPELL_CHECKERS = DidYouMean::SPELL_CHECKERS
|
5
|
+
|
6
|
+
class TestSpellChecker
|
7
|
+
def initialize(*); end
|
8
|
+
def corrections; ["does_exist"]; end
|
9
|
+
end
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@org, SPELL_CHECKERS['NameError'] = SPELL_CHECKERS['NameError'], TestSpellChecker
|
13
|
+
|
14
|
+
@error = assert_raise(NameError){ doesnt_exist }
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
SPELL_CHECKERS['NameError'] = @org
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_message
|
22
|
+
assert_match(/Did you mean\? does_exist/, @error.to_s)
|
23
|
+
assert_match(/Did you mean\? does_exist/, @error.message)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_to_s_does_not_make_disruptive_changes_to_error_message
|
27
|
+
error = assert_raise(NameError) do
|
28
|
+
raise NameError, "uninitialized constant Object"
|
29
|
+
end
|
30
|
+
|
31
|
+
error.to_s
|
32
|
+
assert_equal 1, error.to_s.scan("Did you mean?").count
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_correctable_error_objects_are_dumpable
|
36
|
+
error =
|
37
|
+
begin
|
38
|
+
Dir.chdir(__dir__) { File.open('test_name_error_extension.rb') { |f| f.sizee } }
|
39
|
+
rescue NoMethodError => e
|
40
|
+
e
|
41
|
+
end
|
42
|
+
|
43
|
+
error.to_s
|
44
|
+
|
45
|
+
assert_equal "undefined method `sizee' for #<File:test_name_error_extension.rb (closed)>",
|
46
|
+
Marshal.load(Marshal.dump(error)).original_message
|
47
|
+
end
|
48
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative '../helper'
|
2
2
|
|
3
3
|
# These tests were originally written by Jian Weihang (簡煒航) as part of his work
|
4
4
|
# on the jaro_winkler gem. The original code could be found here:
|
@@ -6,7 +6,7 @@ require 'test_helper'
|
|
6
6
|
#
|
7
7
|
# Copyright (c) 2014 Jian Weihang
|
8
8
|
|
9
|
-
class JaroWinklerTest <
|
9
|
+
class JaroWinklerTest < Test::Unit::TestCase
|
10
10
|
def test_jaro_winkler_distance
|
11
11
|
assert_distance 0.9667, 'henka', 'henkan'
|
12
12
|
assert_distance 1.0, 'al', 'al'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
- test/core_ext/name_error_extension_test.rb
|
3
|
+
- test/edit_distance/jaro_winkler_test.rb
|
4
|
+
- test/fixtures/book.rb
|
5
|
+
- test/spell_checker_test.rb
|
6
|
+
- test/spell_checking/class_name_check_test.rb
|
7
|
+
- test/spell_checking/key_name_check_test.rb
|
8
|
+
- test/spell_checking/method_name_check_test.rb
|
9
|
+
- test/spell_checking/uncorrectable_name_check_test.rb
|
10
|
+
- test/spell_checking/variable_name_check_test.rb
|
11
|
+
- test/test_helper.rb
|
12
|
+
- test/tree_spell_checker_test.rb
|
13
|
+
- test/tree_spell_explore_test.rb
|
14
|
+
- test/tree_spell_human_typo_test.rb
|
15
|
+
- test/verbose_formatter_test.rb
|
@@ -0,0 +1,112 @@
|
|
1
|
+
---
|
2
|
+
- spec/spec_helper.rb
|
3
|
+
- spec/integration/suite_hooks_errors_spec.rb
|
4
|
+
- spec/integration/filtering_spec.rb
|
5
|
+
- spec/integration/spec_file_load_errors_spec.rb
|
6
|
+
- spec/integration/failed_line_detection_spec.rb
|
7
|
+
- spec/integration/persistence_failures_spec.rb
|
8
|
+
- spec/integration/bisect_runners_spec.rb
|
9
|
+
- spec/integration/order_spec.rb
|
10
|
+
- spec/integration/fail_if_no_examples_spec.rb
|
11
|
+
- spec/integration/bisect_spec.rb
|
12
|
+
- spec/integration/output_stream_spec.rb
|
13
|
+
- spec/support/sandboxing.rb
|
14
|
+
- spec/support/spec_files.rb
|
15
|
+
- spec/support/fake_libs/json.rb
|
16
|
+
- spec/support/fake_libs/open3.rb
|
17
|
+
- spec/support/fake_libs/drb/acl.rb
|
18
|
+
- spec/support/fake_libs/drb/drb.rb
|
19
|
+
- spec/support/fake_libs/mocha/api.rb
|
20
|
+
- spec/support/fake_libs/test/unit/assertions.rb
|
21
|
+
- spec/support/fake_libs/flexmock/rspec.rb
|
22
|
+
- spec/support/fake_libs/rake/tasklib.rb
|
23
|
+
- spec/support/fake_libs/coderay.rb
|
24
|
+
- spec/support/fake_libs/rr.rb
|
25
|
+
- spec/support/fake_libs/rake.rb
|
26
|
+
- spec/support/fake_libs/erb.rb
|
27
|
+
- spec/support/fake_libs/rspec/mocks.rb
|
28
|
+
- spec/support/fake_libs/rspec/expectations.rb
|
29
|
+
- spec/support/fake_libs/minitest/assertions.rb
|
30
|
+
- spec/support/fake_libs/minitest.rb
|
31
|
+
- spec/support/matchers.rb
|
32
|
+
- spec/support/runner_support.rb
|
33
|
+
- spec/support/isolated_home_directory.rb
|
34
|
+
- spec/support/config_options_helper.rb
|
35
|
+
- spec/support/mathn_integration_support.rb
|
36
|
+
- spec/support/helper_methods.rb
|
37
|
+
- spec/support/formatter_support.rb
|
38
|
+
- spec/support/fake_bisect_runner.rb
|
39
|
+
- spec/support/shared_example_groups.rb
|
40
|
+
- spec/support/aruba_support.rb
|
41
|
+
- spec/rspec/core/runner_spec.rb
|
42
|
+
- spec/rspec/core/did_you_mean_spec.rb
|
43
|
+
- spec/rspec/core/drb_spec.rb
|
44
|
+
- spec/rspec/core/metadata_spec.rb
|
45
|
+
- spec/rspec/core/example_group_spec.rb
|
46
|
+
- spec/rspec/core/configuration/only_failures_support_spec.rb
|
47
|
+
- spec/rspec/core/rake_task_spec.rb
|
48
|
+
- spec/rspec/core/memoized_helpers_spec.rb
|
49
|
+
- spec/rspec/core/ordering_spec.rb
|
50
|
+
- spec/rspec/core/option_parser_spec.rb
|
51
|
+
- spec/rspec/core/example_execution_result_spec.rb
|
52
|
+
- spec/rspec/core/suite_hooks_spec.rb
|
53
|
+
- spec/rspec/core/set_spec.rb
|
54
|
+
- spec/rspec/core/configuration_spec.rb
|
55
|
+
- spec/rspec/core/rspec_matchers_spec.rb
|
56
|
+
- spec/rspec/core/hooks_filtering_spec.rb
|
57
|
+
- spec/rspec/core/bisect/shell_command_spec.rb
|
58
|
+
- spec/rspec/core/bisect/server_spec.rb
|
59
|
+
- spec/rspec/core/bisect/example_minimizer_spec.rb
|
60
|
+
- spec/rspec/core/bisect/shell_runner_spec.rb
|
61
|
+
- spec/rspec/core/bisect/utilities_spec.rb
|
62
|
+
- spec/rspec/core/bisect/coordinator_spec.rb
|
63
|
+
- spec/rspec/core/resources/a_foo.rb
|
64
|
+
- spec/rspec/core/resources/formatter_specs.rb
|
65
|
+
- spec/rspec/core/resources/inconsistently_ordered_specs.rb
|
66
|
+
- spec/rspec/core/resources/a_bar.rb
|
67
|
+
- spec/rspec/core/resources/utf8_encoded.rb
|
68
|
+
- spec/rspec/core/resources/a_spec.rb
|
69
|
+
- spec/rspec/core/resources/acceptance/bar.rb
|
70
|
+
- spec/rspec/core/resources/acceptance/foo_spec.rb
|
71
|
+
- spec/rspec/core/resources/custom_example_group_runner.rb
|
72
|
+
- spec/rspec/core/failed_example_notification_spec.rb
|
73
|
+
- spec/rspec/core/hooks_spec.rb
|
74
|
+
- spec/rspec/core/formatters/profile_formatter_spec.rb
|
75
|
+
- spec/rspec/core/formatters/deprecation_formatter_spec.rb
|
76
|
+
- spec/rspec/core/formatters/syntax_highlighter_spec.rb
|
77
|
+
- spec/rspec/core/formatters/base_text_formatter_spec.rb
|
78
|
+
- spec/rspec/core/formatters/snippet_extractor_spec.rb
|
79
|
+
- spec/rspec/core/formatters/progress_formatter_spec.rb
|
80
|
+
- spec/rspec/core/formatters/html_snippet_extractor_spec.rb
|
81
|
+
- spec/rspec/core/formatters/helpers_spec.rb
|
82
|
+
- spec/rspec/core/formatters/html_formatter_spec.rb
|
83
|
+
- spec/rspec/core/formatters/json_formatter_spec.rb
|
84
|
+
- spec/rspec/core/formatters/documentation_formatter_spec.rb
|
85
|
+
- spec/rspec/core/formatters/exception_presenter_spec.rb
|
86
|
+
- spec/rspec/core/formatters/console_codes_spec.rb
|
87
|
+
- spec/rspec/core/formatters/fallback_message_formatter_spec.rb
|
88
|
+
- spec/rspec/core/invocations_spec.rb
|
89
|
+
- spec/rspec/core/configuration_options_spec.rb
|
90
|
+
- spec/rspec/core/pending_spec.rb
|
91
|
+
- spec/rspec/core/profiler_spec.rb
|
92
|
+
- spec/rspec/core/project_initializer_spec.rb
|
93
|
+
- spec/rspec/core/aggregate_failures_spec.rb
|
94
|
+
- spec/rspec/core/dsl_spec.rb
|
95
|
+
- spec/rspec/core/ruby_project_spec.rb
|
96
|
+
- spec/rspec/core/formatters_spec.rb
|
97
|
+
- spec/rspec/core/metadata_filter_spec.rb
|
98
|
+
- spec/rspec/core/example_group_constants_spec.rb
|
99
|
+
- spec/rspec/core/world_spec.rb
|
100
|
+
- spec/rspec/core/shared_context_spec.rb
|
101
|
+
- spec/rspec/core/pending_example_spec.rb
|
102
|
+
- spec/rspec/core/filter_manager_spec.rb
|
103
|
+
- spec/rspec/core/shared_example_group_spec.rb
|
104
|
+
- spec/rspec/core/example_status_persister_spec.rb
|
105
|
+
- spec/rspec/core/backtrace_formatter_spec.rb
|
106
|
+
- spec/rspec/core/output_wrapper_spec.rb
|
107
|
+
- spec/rspec/core/example_spec.rb
|
108
|
+
- spec/rspec/core/reporter_spec.rb
|
109
|
+
- spec/rspec/core/filterable_item_repository_spec.rb
|
110
|
+
- spec/rspec/core/notifications_spec.rb
|
111
|
+
- spec/rspec/core/warnings_spec.rb
|
112
|
+
- spec/rspec/core_spec.rb
|
data/test/helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
module DidYouMean
|
4
|
+
module TestHelper
|
5
|
+
class << self
|
6
|
+
attr_reader :root
|
7
|
+
end
|
8
|
+
|
9
|
+
if File.file?(File.expand_path('../lib/did_you_mean.rb', __dir__))
|
10
|
+
# In this case we're being run from inside the gem, so we just want to
|
11
|
+
# require the root of the library
|
12
|
+
|
13
|
+
@root = File.expand_path('../lib/did_you_mean', __dir__)
|
14
|
+
require_relative @root
|
15
|
+
else
|
16
|
+
# In this case we're being run from inside ruby core, and we want to
|
17
|
+
# include the experimental features in the test suite
|
18
|
+
|
19
|
+
@root = File.expand_path('../../lib/did_you_mean', __dir__)
|
20
|
+
require_relative @root
|
21
|
+
# We are excluding experimental features for now.
|
22
|
+
# require_relative File.join(@root, 'experimental')
|
23
|
+
end
|
24
|
+
|
25
|
+
def assert_correction(expected, array)
|
26
|
+
assert_equal Array(expected), array, "Expected #{array.inspect} to only include #{expected.inspect}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|