New upstream version 0.0.41.3
Sophie Brun
5 years ago
19 | 19 | - 2.5.1 |
20 | 20 | - 2.5.2 |
21 | 21 | - 2.5.3 |
22 | - 2.6.0 | |
22 | 23 | - ruby-head |
23 | 24 | before_install: |
24 | 25 | - "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" |
25 | - "gem update --system" | |
26 | - gem update --system | |
26 | 27 | matrix: |
27 | 28 | allow_failures: |
28 | 29 | - rvm: ruby-head |
3 | 3 | [![Build Status](https://img.shields.io/travis/wpscanteam/CMSScanner.svg)](https://travis-ci.org/wpscanteam/CMSScanner) |
4 | 4 | [![Coverage Status](https://img.shields.io/coveralls/wpscanteam/CMSScanner.svg)](https://coveralls.io/r/wpscanteam/CMSScanner) |
5 | 5 | [![Code Climate](https://api.codeclimate.com/v1/badges/b90b7f9f6982792ef8d6/maintainability)](https://codeclimate.com/github/wpscanteam/CMSScanner/maintainability) |
6 | [![Dependency Status](https://img.shields.io/gemnasium/wpscanteam/CMSScanner.svg)](https://gemnasium.com/wpscanteam/CMSScanner) | |
7 | 6 | |
8 | 7 | The goal of this gem is to provide a quick and easy way to create a CMS/WebSite Scanner by acting like a Framework and providing classes, formatters etc. |
9 | 8 |
30 | 30 | OptBoolean.new(['--ignore-main-redirect', 'Ignore the main redirect (if any) and scan the target url'], |
31 | 31 | advanced: true), |
32 | 32 | OptBoolean.new(['-v', '--verbose', 'Verbose mode']), |
33 | OptBoolean.new(['--[no-]banner', 'Whether or not to display the banner'], default: true) | |
33 | OptBoolean.new(['--[no-]banner', 'Whether or not to display the banner'], default: true), | |
34 | OptPositiveInteger.new(['--max-scan-duration SECONDS', | |
35 | 'Abort the scan if it exceeds the time provided in seconds'], | |
36 | advanced: true) | |
34 | 37 | ] |
35 | 38 | end |
36 | 39 |
18 | 18 | s.test_files = [] |
19 | 19 | s.require_paths = ['lib'] |
20 | 20 | |
21 | s.add_dependency 'nokogiri', '~> 1.8.0' | |
22 | s.add_dependency 'opt_parse_validator', '~> 0.0.16.5' | |
21 | s.add_dependency 'nokogiri', '~> 1.10.0' | |
22 | s.add_dependency 'opt_parse_validator', '~> 0.0.16.6' | |
23 | 23 | s.add_dependency 'public_suffix', '~> 3.0.0' |
24 | 24 | s.add_dependency 'ruby-progressbar', '~> 1.10.0' |
25 | 25 | s.add_dependency 'typhoeus', '~> 1.3.0' |
26 | 26 | s.add_dependency 'xmlrpc', '~> 0.3' |
27 | 27 | s.add_dependency 'yajl-ruby', '~> 1.4.1' # Better JSON parser regarding memory usage |
28 | 28 | |
29 | # Already required by opt_parse_validator | |
30 | # so version restriction loosen to avoid potential future conflicts | |
31 | s.add_dependency 'activesupport', '~> 5.1' | |
32 | s.add_dependency 'addressable', '~> 2.5' | |
33 | ||
34 | s.add_development_dependency 'bundler', '~> 1.6' | |
29 | s.add_development_dependency 'bundler', '>= 1.6' | |
35 | 30 | s.add_development_dependency 'coveralls', '~> 0.8.0' |
36 | 31 | s.add_development_dependency 'rake', '~> 12.3' |
37 | 32 | s.add_development_dependency 'rspec', '~> 3.8.0' |
38 | 33 | s.add_development_dependency 'rspec-its', '~> 1.2.0' |
39 | s.add_development_dependency 'rubocop', '~> 0.61.1' | |
34 | s.add_development_dependency 'rubocop', '~> 0.62.0' | |
40 | 35 | s.add_development_dependency 'simplecov', '~> 0.16.1' |
41 | 36 | s.add_development_dependency 'webmock', '~> 3.5.1' |
42 | 37 | end |
6 | 6 | - 2.3.2 |
7 | 7 | - 2.3.3 |
8 | 8 | - 2.3.4 |
9 | - 2.4.0 | |
9 | - 2.3.5 | |
10 | - 2.3.6 | |
11 | - 2.3.7 | |
12 | - 2.3.8 | |
10 | 13 | - 2.4.1 |
14 | - 2.4.2 | |
15 | - 2.4.3 | |
16 | - 2.4.4 | |
17 | - 2.4.5 | |
18 | - 2.5.0 | |
19 | - 2.5.1 | |
20 | - 2.5.2 | |
21 | - 2.5.3 | |
22 | - 2.6.0 | |
11 | 23 | - ruby-head |
12 | 24 | before_install: |
13 | 25 | - "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" |
14 | - "gem update --system" | |
26 | - gem update --system | |
15 | 27 | matrix: |
16 | 28 | allow_failures: |
17 | 29 | - rvm: ruby-head |
18 | 30 | script: |
31 | - bundle exec rubocop | |
19 | 32 | - bundle exec rspec |
20 | - bundle exec rubocop |
0 | # coding: utf-8 | |
1 | ||
2 | 0 | lib = File.expand_path('../lib', __FILE__) |
3 | 1 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) |
4 | 2 | |
8 | 6 | s.name = 'cmsscan' |
9 | 7 | s.version = CMSScan::VERSION |
10 | 8 | s.platform = Gem::Platform::RUBY |
11 | s.required_ruby_version = '>= 2.1.0' | |
9 | s.required_ruby_version = '>= 2.3' | |
12 | 10 | s.authors = ['WPScanTeam'] |
13 | 11 | s.date = Time.now.utc.strftime('%Y-%m-%d') |
14 | 12 | s.email = ['[email protected]'] |
17 | 15 | s.homepage = 'https://github.com/wpscanteam/CMSScanner' |
18 | 16 | s.license = 'MIT' |
19 | 17 | |
20 | s.files = `git ls-files -z`.split("\x0").reject do |file| | |
21 | file =~ %r{^(?: | |
22 | spec\/.* | |
23 | |Gemfile | |
24 | |Rakefile | |
25 | |\.rspec | |
26 | |\.gitignore | |
27 | |\.rubocop.yml | |
28 | |\.travis.yml | |
29 | )$}x | |
30 | end | |
18 | s.files = Dir.glob('lib/**/*') + Dir.glob('app/**/*') | |
19 | s.test_files = [] | |
20 | s.executables = ['cmsscan'] | |
21 | s.require_paths = ['lib'] | |
31 | 22 | |
32 | s.test_files = [] | |
33 | s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) } | |
34 | s.require_path = 'lib' | |
23 | s.add_dependency 'cms_scanner', '~> 0.0.41.1' | |
35 | 24 | |
36 | s.add_dependency 'cms_scanner', '~> 0.0.39.0' | |
37 | ||
38 | # Already required by CMSScanner, so version restrictions loosen | |
39 | s.add_dependency 'activesupport', '~> 5.1' | |
40 | s.add_dependency 'yajl-ruby', '~> 1.3' | |
41 | ||
42 | s.add_development_dependency 'bundler', '~> 1.6' | |
25 | s.add_development_dependency 'bundler', '>= 1.6' | |
43 | 26 | s.add_development_dependency 'coveralls', '~> 0.8.0' |
44 | s.add_development_dependency 'rake', '~> 12.0' | |
45 | s.add_development_dependency 'rspec', '~> 3.7.0' | |
27 | s.add_development_dependency 'rake', '~> 12.3' | |
28 | s.add_development_dependency 'rspec', '~> 3.8.0' | |
46 | 29 | s.add_development_dependency 'rspec-its', '~> 1.2.0' |
47 | s.add_development_dependency 'rubocop', '~> 0.52.0' | |
48 | s.add_development_dependency 'simplecov', '~> 0.14.0' # Can't update to 0.15 as it breaks coveralls dep | |
49 | s.add_development_dependency 'webmock', '~> 3.3.0' | |
30 | s.add_development_dependency 'rubocop', '~> 0.62.0' | |
31 | s.add_development_dependency 'simplecov', '~> 0.16.1' | |
32 | s.add_development_dependency 'webmock', '~> 3.5.1' | |
50 | 33 | end |
0 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) | |
1 | ||
2 | require 'simplecov' | |
3 | require 'rspec/its' | |
4 | require 'webmock/rspec' | |
5 | ||
6 | require 'cmsscan' | |
7 | ||
8 | if ENV['TRAVIS'] | |
9 | require 'coveralls' | |
10 | SimpleCov.formatter = Coveralls::SimpleCov::Formatter | |
11 | end | |
12 | ||
13 | # See http://betterspecs.org/ | |
14 | RSpec.configure do |config| | |
15 | config.expect_with :rspec do |c| | |
16 | c.syntax = :expect | |
17 | end | |
18 | end |
38 | 38 | |
39 | 39 | redirect_output_to_file(parsed_options[:output]) if parsed_options[:output] |
40 | 40 | |
41 | each(&:before_scan) | |
42 | each(&:run) | |
43 | # Reverse is used here as the app/controllers/core#after_scan finishes the output | |
44 | # and must be the last one to be executed | |
45 | reverse_each(&:after_scan) | |
41 | Timeout.timeout(parsed_options[:max_scan_duration], NS::MaxScanDurationReachedError) do | |
42 | each(&:before_scan) | |
43 | each(&:run) | |
44 | # Reverse is used here as the app/controllers/core#after_scan finishes the output | |
45 | # and must be the last one to be executed | |
46 | reverse_each(&:after_scan) | |
47 | end | |
46 | 48 | end |
47 | 49 | end |
48 | 50 | end |
0 | module CMSScanner | |
1 | # Used instead of the Timeout::Error | |
2 | class MaxScanDurationReachedError < Error | |
3 | # :nocov: | |
4 | def to_s | |
5 | 'Max Scan Duration Reached' | |
6 | end | |
7 | # :nocov: | |
8 | end | |
9 | end |
0 | 0 | # Version |
1 | 1 | module CMSScanner |
2 | VERSION = '0.0.41.1'.freeze | |
2 | VERSION = '0.0.41.3'.freeze | |
3 | 3 | end |
12 | 12 | require 'uri' |
13 | 13 | require 'fileutils' |
14 | 14 | require 'pathname' |
15 | require 'timeout' | |
15 | 16 | require 'xmlrpc/client' |
16 | 17 | # Monkey Patches |
17 | 18 | require 'cms_scanner/typhoeus/response' # Adds a Response#html using Nokogiri to parse the body |
23 | 24 | require 'cms_scanner/helper' |
24 | 25 | require 'cms_scanner/exit_code' |
25 | 26 | require 'cms_scanner/errors/http' |
27 | require 'cms_scanner/errors/scan' | |
26 | 28 | require 'cms_scanner/cache/typhoeus' |
27 | 29 | require 'cms_scanner/target' |
28 | 30 | require 'cms_scanner/browser' |
184 | 186 | |
185 | 187 | return NS::ExitCode::INTERRUPTED if run_error.is_a?(Interrupt) |
186 | 188 | |
187 | return NS::ExitCode::ERROR if run_error.is_a?(NS::Error) | |
189 | return NS::ExitCode::ERROR if run_error.is_a?(NS::Error) || run_error.is_a?(CMSScanner::Error) | |
188 | 190 | |
189 | 191 | NS::ExitCode::EXCEPTION |
190 | 192 | end |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Controller::Core do |
3 | 1 | subject(:core) { described_class.new } |
4 | 2 | let(:target_url) { 'http://example.com/' } |
19 | 17 | %i[ |
20 | 18 | banner cache_dir cache_ttl clear_cache connect_timeout cookie_jar cookie_string |
21 | 19 | detection_mode disable_tls_checks format headers help hh http_auth ignore_main_redirect |
22 | max_threads output proxy proxy_auth random_user_agent request_timeout scope | |
23 | throttle url user_agent user_agents_list verbose version vhost | |
20 | max_scan_duration max_threads output proxy proxy_auth random_user_agent request_timeout | |
21 | scope throttle url user_agent user_agents_list verbose version vhost | |
24 | 22 | ] |
25 | 23 | ) |
26 | 24 | end |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Controller::InterestingFindings do |
3 | 1 | subject(:controller) { described_class.new } |
4 | 2 | let(:target_url) { 'http://example.com/' } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Finders::InterestingFindings::FantasticoFileslist do |
3 | 1 | subject(:finder) { described_class.new(target) } |
4 | 2 | let(:target) { CMSScanner::Target.new(url) } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Finders::InterestingFindings::Headers do |
3 | 1 | subject(:finder) { described_class.new(target) } |
4 | 2 | let(:target) { CMSScanner::Target.new(url) } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Finders::InterestingFindings::RobotsTxt do |
3 | 1 | subject(:finder) { described_class.new(target) } |
4 | 2 | let(:target) { CMSScanner::Target.new(url) } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Finders::InterestingFindings::SearchReplaceDB2 do |
3 | 1 | subject(:finder) { described_class.new(target) } |
4 | 2 | let(:target) { CMSScanner::Target.new(url) } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Finders::InterestingFindings::XMLRPC do |
3 | 1 | subject(:finder) { described_class.new(target) } |
4 | 2 | let(:target) { CMSScanner::Target.new(url) } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Finders::InterestingFindings::Base do |
3 | 1 | it_behaves_like CMSScanner::Finders::IndependentFinder do |
4 | 2 | let(:expected_finders) { %w[Headers RobotsTxt FantasticoFileslist SearchReplaceDB2 XMLRPC] } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Formatter::CliNoColour do |
3 | 1 | subject(:formatter) { described_class.new } |
4 | 2 |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Formatter::Cli do |
3 | 1 | subject(:formatter) { described_class.new } |
4 | 2 |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Formatter::Json do |
3 | 1 | it_behaves_like CMSScanner::Formatter::Buffer |
4 | 2 |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::FantasticoFileslist do |
3 | 1 | subject(:file) { described_class.new(url) } |
4 | 2 | let(:url) { 'http://example.com/robots.txt' } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Headers do |
3 | 1 | subject(:file) { described_class.new(url) } |
4 | 2 | let(:url) { 'http://example.com/' } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::InterestingFinding do |
3 | 1 | it_behaves_like CMSScanner::Finders::Finding |
4 | 2 |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::RobotsTxt do |
3 | 1 | subject(:file) { described_class.new(url) } |
4 | 2 | let(:url) { 'http://example.com/robots.txt' } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::User do |
3 | 1 | subject(:user) { described_class.new(username, opts) } |
4 | 2 | let(:username) { 'john' } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Version do |
3 | 1 | it_behaves_like CMSScanner::Finders::Finding |
4 | 2 |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::XMLRPC do |
3 | 1 | subject(:xml_rpc) { described_class.new(url) } |
4 | 2 | let(:url) { 'http://example.com/xmlrpc' } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe 'App::Views' do |
3 | 1 | let(:target_url) { 'http://e.org/' } |
4 | 2 | let(:fixtures) { SPECS.join('output') } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Browser do |
3 | 1 | it_behaves_like described_class::Actions |
4 | 2 |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Cache::FileStore do |
3 | 1 | let(:cache_dir) { CACHE.join('cache_file_store').to_s } |
4 | 2 | subject(:cache) { described_class.new(cache_dir) } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Cache::Typhoeus do |
3 | 1 | subject(:cache) { described_class.new(cache_dir) } |
4 | 2 |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner do |
3 | 1 | let(:target_url) { 'http://wp.lab/' } |
4 | 2 | |
103 | 101 | |
104 | 102 | [RuntimeError.new('error spotted'), |
105 | 103 | CMSScanner::Error.new('aa'), |
104 | CMSScanner::MaxScanDurationReachedError.new, | |
106 | 105 | SignalException.new('SIGTERM'), |
107 | 106 | Interrupt.new('Canceled by User')].each do |error| |
108 | 107 | context "when an/a #{error.class} is raised during the scan" do |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Controller do |
3 | 1 | subject(:controller) { described_class::Base.new } |
4 | 2 |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | module CMSScanner |
3 | 1 | module Controller |
4 | 2 | class Spec < Base |
3 | end | |
4 | ||
5 | class SpecTooLong < Spec | |
6 | def run | |
7 | sleep(2) | |
8 | end | |
5 | 9 | end |
6 | 10 | end |
7 | 11 | end |
47 | 51 | |
48 | 52 | controllers.run |
49 | 53 | end |
54 | ||
55 | context 'when max_scan_duration is provided' do | |
56 | before do | |
57 | expect(controllers.option_parser).to receive(:results) | |
58 | .and_return(max_scan_duration: max_scan_duration) | |
59 | ||
60 | controllers << controller_mod::Spec.new << controller_mod::SpecTooLong.new | |
61 | end | |
62 | ||
63 | context 'when the scan exceeds the max duration' do | |
64 | let(:max_scan_duration) { 1 } | |
65 | ||
66 | it 'raises an exception' do | |
67 | expect { controllers.run }.to raise_error(CMSScanner::MaxScanDurationReachedError) | |
68 | end | |
69 | end | |
70 | ||
71 | context 'when the scan does not exceed to max duration' do | |
72 | let(:max_scan_duration) { 4 } | |
73 | ||
74 | it 'does not raise an exception' do | |
75 | expect { controllers.run }.to_not raise_error | |
76 | end | |
77 | end | |
78 | end | |
50 | 79 | end |
51 | 80 | |
52 | 81 | describe '#register_options_files' do |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Finders::Finder::BreadthFirstDictionaryAttack do |
3 | 1 | # Dummy class to test the module |
4 | 2 | class DummyBreadthFirstDictionaryAttack < CMSScanner::Finders::Finder |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Finders::Finder::Enumerator do |
3 | 1 | # Dummy class to test the module |
4 | 2 | class DummyEnumeratorFinder < CMSScanner::Finders::Finder |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Finders::Finder::Fingerprinter do |
3 | 1 | # Dummy class to test the module |
4 | 2 | class DummyFingerprinterFinder < CMSScanner::Finders::Finder |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Finders::Finder::SmartURLChecker do |
3 | 1 | # Dummy class to test the module |
4 | 2 | class DummyFinder < CMSScanner::Finders::Finder |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Finders::Finder do |
3 | 1 | subject(:finder) { described_class.new('target') } |
4 | 2 |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | module CMSScanner |
3 | 1 | module Finders |
4 | 2 | # Dummy Class to test the module |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | module CMSScanner |
3 | 1 | module Finders |
4 | 2 | # Dummy Class to test the module |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe Numeric do |
3 | 1 | describe '#bytes_to_human' do |
4 | 2 | context 'when positive' do |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::ProgressBarNullOutput do |
3 | 1 | subject(:output) { described_class.new } |
4 | 2 |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe PublicSuffix::Domain do |
3 | 1 | describe '#match' do |
4 | 2 | it 'returns true' do |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe 'SubScanner' do |
3 | 1 | before :all do |
4 | 2 | # Module including the CMSScanner to test its correct inclusion |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Target do |
3 | 1 | subject(:target) { described_class.new(url) } |
4 | 2 | let(:url) { 'http://e.org' } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | [:PHP].each do |platform| |
3 | 1 | describe CMSScanner::Target do |
4 | 2 | subject(:target) do |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Target do |
3 | 1 | subject(:target) { described_class.new(url, opts) } |
4 | 2 | let(:url) { 'http://e.org' } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | %i[Generic Apache IIS Nginx].each do |server| |
3 | 1 | describe CMSScanner::Target do |
4 | 2 | subject(:target) do |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Target do |
3 | 1 | subject(:target) { described_class.new(url) } |
4 | 2 | let(:url) { 'http://e.org' } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe Typhoeus::Response do |
3 | 1 | subject(:response) { Typhoeus::Response.new(opts) } |
4 | 2 | let(:opts) { { body: 'hello world' } } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::Vulnerability do |
3 | 1 | subject(:vuln) { described_class.new(title, references) } |
4 | 2 | let(:title) { 'Test Vuln' } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | describe CMSScanner::WebSite do |
3 | 1 | subject(:web_site) { described_class.new(url, opts) } |
4 | 2 | let(:url) { 'http://e.org' } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | shared_examples CMSScanner::Target::Server::Apache do |
3 | 1 | describe '#server' do |
4 | 2 | its(:server) { should eq :Apache } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | shared_examples CMSScanner::Target::Server::Generic do |
3 | 1 | describe '#server' do |
4 | 2 | before { stub_request(:head, target.url).to_return(headers: parse_headers_file(fixture)) } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | shared_examples CMSScanner::Target::Server::IIS do |
3 | 1 | describe '#server' do |
4 | 2 | its(:server) { should eq :IIS } |
0 | require 'spec_helper' | |
1 | ||
2 | 0 | shared_examples CMSScanner::Target::Server::Nginx do |
3 | 1 | describe '#server' do |
4 | 2 | its(:server) { should eq :Nginx } |
0 | 0 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) |
1 | 1 | |
2 | require 'simplecov' | |
2 | require 'simplecov' # Used filters are in /.simplecov | |
3 | 3 | require 'rspec/its' |
4 | 4 | require 'webmock/rspec' |
5 | 5 | require 'active_support/time' |
7 | 7 | if ENV['TRAVIS'] |
8 | 8 | require 'coveralls' |
9 | 9 | SimpleCov.formatter = Coveralls::SimpleCov::Formatter |
10 | end | |
11 | ||
12 | SimpleCov.start do | |
13 | add_filter '/example/' | |
14 | add_filter '/spec/' | |
15 | add_filter 'helper' | |
16 | 10 | end |
17 | 11 | |
18 | 12 | # See http://betterspecs.org/ |