diff --git a/lib/common/models/wp_item.rb b/lib/common/models/wp_item.rb index 2ecc09d8..9525ee22 100755 --- a/lib/common/models/wp_item.rb +++ b/lib/common/models/wp_item.rb @@ -23,8 +23,10 @@ class WpItem [:name, :wp_content_dir, :wp_plugins_dir, :path, :version, :vulns_file] end - # options : - # See allowed_options + # @param [ URI ] target_base_uri + # @param [ Hash ] options See allowed_option + # + # @return [ WpItem ] def initialize(target_base_uri, options = {}) options[:wp_content_dir] ||= 'wp-content' @@ -34,6 +36,9 @@ class WpItem forge_uri(target_base_uri) end + # @param [ Hash ] options + # + # @return [ void ] def set_options(options) allowed_options.each do |allowed_option| if options.has_key?(allowed_option) @@ -49,30 +54,46 @@ class WpItem end private :set_options + # @param [ URI ] target_base_uri + # + # @return [ void ] def forge_uri(target_base_uri) @uri = target_base_uri end + # @return [ URI ] The uri to the WpItem, with the path if present def uri - return path ? @uri.merge(path) : @uri + path ? @uri.merge(path) : @uri end + # @return [ String ] The url to the WpItem def url; uri.to_s end + # Sets the path + # + # Variable, such as $wp-plugins$ and $wp-content$ can be used + # and will be replace by their value + # + # @param [ String ] path + # + # @return [ void ] def path=(path) @path = URI.encode( path.gsub(/\$wp-plugins\$/i, wp_plugins_dir).gsub(/\$wp-content\$/i, wp_content_dir) ) end + # @param [ WpItem ] other def <=>(other) name <=> other.name end + # @param [ WpItem ] other def ==(other) name === other.name end + # @param [ WpItem ] other def ===(other) self == other && version === other.version end diff --git a/spec/lib/common/models/wp_item_spec.rb b/spec/lib/common/models/wp_item_spec.rb new file mode 100644 index 00000000..23d468b0 --- /dev/null +++ b/spec/lib/common/models/wp_item_spec.rb @@ -0,0 +1,149 @@ +# encoding: UTF-8 + +require 'spec_helper' + +describe WpItem do + subject(:wp_item) { WpItem.new(uri, options) } + let(:uri) { URI.parse('http://example.com') } + let(:options) { {} } + + describe '#new' do + context 'with no options' do + its(:wp_content_dir) { should == 'wp-content' } + its(:wp_plugins_dir) { should == 'wp-content/plugins' } + its(:uri) { should be uri } + end + + context 'with :wp_content_dir' do + let(:options) { { wp_content_dir: 'custom' } } + + its(:wp_content_dir) { should == 'custom' } + its(:wp_plugins_dir) { should == 'custom/plugins' } + end + + context 'with :wp_plugins_dir' do + let(:options) { { wp_plugins_dir: 'c-plugins' } } + + its(:wp_content_dir) { should == 'wp-content' } + its(:wp_plugins_dir) { should == 'c-plugins' } + end + end + + describe '#set_options' do + context 'no an allowed option' do + it 'ignores the option' do + wp_item.should_not_receive(:not_allowed=) + + wp_item.send(:set_options, { not_allowed: 'owned' }) + end + end + + context 'allowed option, w/o setter method' do + it 'raises an error' do + wp_item.stub(:allowed_options).and_return([:no_setter]) + + expect { + wp_item.send(:set_options, { no_setter: 'hello' }) + }.to raise_error('WpItem does not respond to no_setter=') + end + end + end + + describe '#path=' do + after do + wp_item.path = @path + wp_item.path.should == @expected + end + + context 'with default variable value' do + it 'replaces $wp-content$ by wp-content' do + @path = '$wp-content$/hello' + @expected = 'wp-content/hello' + end + + it 'replaces $wp-plugins$ by wp-content/plugins' do + @path = '$wp-plugins$/yolo/file.php' + @expected = 'wp-content/plugins/yolo/file.php' + end + end + + context 'whith custom variable values' do + before { + wp_item.stub(:wp_content_dir).and_return('custom-content') + wp_item.stub(:wp_plugins_dir).and_return('plugins') + } + + it 'replaces $wp-content$ by custom-content' do + @path = '$wp-content$/file.php' + @expected = 'custom-content/file.php' + end + + it 'replaces $wp-plugins$ by plugins' do + @path = '$wp-plugins$/readme.txt' + @expected = 'plugins/readme.txt' + end + end + + it 'also encodes chars' do + @path = 'some dir with spaces' + @expected = 'some%20dir%20with%20spaces' + end + end + + describe '#uri' do + context 'when the path is present' do + it 'returns it with the uri' do + path = 'somedir/somefile.php' + wp_item.path = path + + wp_item.uri.should == uri.merge(path) + end + end + end + + describe '#<=>' do + it 'bases the comparaison on the :name' do + wp_item.name = 'a-name' + other = WpItem.new(uri, name: 'other-name') + + wp_item.<=>(other).should === 'a-name'.<=>('other-name') + end + end + + describe '#==' do + context 'when the :name is the same' do + it 'is ==' do + wp_item.name = 'some-name' + other = WpItem.new(uri, name: 'some-name') + + wp_item.should == other + end + end + + context 'otherwise' do + it 'is not ==' do + wp_item.name = 'Test' + other = WpItem.new(uri, name: 'hello') + + wp_item.should_not == other + end + end + end + + describe '#===' do + let(:options) { { name: 'a-name', version: '1.2' } } + + context 'when the :name and :version are the same' do + it 'is ===' do + WpItem.new(uri, options).should === WpItem.new(uri.merge('yo'), options) + end + end + + context 'otherwise' do + it 'is not ===' do + WpItem.new(uri, options).should_not === WpItem.new(uri, options.merge(version: '1.0')) + end + end + end + +end