Skip to content

Commit

Permalink
Add prototype model for GemTypo
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan Claudius authored and sonalkr132 committed Jun 13, 2019
1 parent c50c5d1 commit 9563103
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 0 deletions.
46 changes: 46 additions & 0 deletions app/models/gem_typo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'rubygems/text'

class GemTypo
PROTECTED_GEMS = [
'rspec-core',
'diff-lcs',
'rspec-expectations',
'rspec-mocks',
'rspec',
'bundler',
'rspec-support',
'multi_json',
'rack',
'rake'
].freeze

DISTANCE_THRESHOLD = 1

GEM_EXCEPTIONS = [
'rspec-coreZ'
# Add exceptions here to manage gems which share a close distance,
# but are manually reviewed and accepted by rubygems team
].freeze

include Gem::Text

def initialize(rubygem_name, opts = {})
@rubygem_name = rubygem_name
@protected_gems = opts[:protected_gems] || GemTypo::PROTECTED_GEMS
@distance_threshold = opts[:distance_threshold] || GemTypo::DISTANCE_THRESHOLD
@gem_exceptions = opts[:gem_exceptions] || GemTypo::GEM_EXCEPTIONS
end

def protected_typo?
@protected_gems.each do |protected_gem|
return false if @rubygem_name == protected_gem
distance = levenshtein_distance(@rubygem_name, protected_gem)
if distance <= @distance_threshold &&
!@gem_exceptions.include?(@rubygem_name)
return true
end
end

false
end
end
78 changes: 78 additions & 0 deletions test/unit/gem_typo_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
require 'test_helper'
require 'gem_typo'

class GemTypoTest < ActiveSupport::TestCase
teardown do
Rails.cache.clear
end

should 'return false for exact match' do
gem_typo = GemTypo.new('rspec-core')
assert_equal false, gem_typo.protected_typo?
end

should 'return true for 1 char distance match' do
gem_typo = GemTypo.new('rspec-core2')
assert_equal true, gem_typo.protected_typo?
end

should 'return false for 2 char distance match' do
gem_typo = GemTypo.new('rspec-core12')
assert_equal false, gem_typo.protected_typo?
end

should 'return false for 3 char distance match' do
gem_typo = GemTypo.new('rspec-core123')
assert_equal false, gem_typo.protected_typo?
end

should 'return false for 1 char distance match on the exception list' do
gem_typo = GemTypo.new('rspec-coreZ')
assert_equal false, gem_typo.protected_typo?
end

should 'allow customized protected_gems' do
opts = {
protected_gems: ["hello"]
}

gem_typo = GemTypo.new('hello', opts)
assert_equal false, gem_typo.protected_typo?

gem_typo = GemTypo.new('hello1', opts)
assert_equal true, gem_typo.protected_typo?
end

should 'allow customized distance_threshold' do
opts = {
distance_threshold: 3
}

gem_typo = GemTypo.new('rack', opts)
assert_equal false, gem_typo.protected_typo?

gem_typo = GemTypo.new('rack1', opts)
assert_equal true, gem_typo.protected_typo?

gem_typo = GemTypo.new('rack12', opts)
assert_equal true, gem_typo.protected_typo?

gem_typo = GemTypo.new('rack123', opts)
assert_equal true, gem_typo.protected_typo?

gem_typo = GemTypo.new('rack1234', opts)
assert_equal false, gem_typo.protected_typo?
end

should 'allow customized protected_gem_exceptions' do
opts = {
gem_exceptions: ["rake1"]
}

gem_typo = GemTypo.new('rake', opts)
assert_equal false, gem_typo.protected_typo?

gem_typo = GemTypo.new('rake1', opts)
assert_equal false, gem_typo.protected_typo?
end
end

0 comments on commit 9563103

Please sign in to comment.