hit_counter 0.1.3 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +5 -13
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +23 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
  5. data/.github/ISSUE_TEMPLATE/task.md +21 -0
  6. data/.github/PULL_REQUEST_TEMPLATE.md +31 -0
  7. data/.github/dependabot.yml +11 -0
  8. data/.github/workflows/test.yml +42 -0
  9. data/.gitignore +2 -1
  10. data/.simplecov +15 -0
  11. data/CODE_OF_CONDUCT.md +10 -0
  12. data/CONTRIBUTING.md +34 -0
  13. data/Gemfile +14 -2
  14. data/LICENSE.txt +17 -11
  15. data/README.md +120 -0
  16. data/Rakefile +16 -1
  17. data/SECURITY.md +16 -0
  18. data/certs/ivanoblomov.pem +25 -0
  19. data/config/initializers/mime_types.rb +3 -1
  20. data/config/mongoid.yml +2 -2
  21. data/hit_counter.gemspec +20 -18
  22. data/lib/hit_counter.rb +86 -90
  23. data/lib/tasks/install.rake +6 -0
  24. data/lib/version.rb +5 -1
  25. data/public/images/digits/celtic/0.png +0 -0
  26. data/public/images/digits/celtic/1.png +0 -0
  27. data/public/images/digits/celtic/2.png +0 -0
  28. data/public/images/digits/celtic/3.png +0 -0
  29. data/public/images/digits/celtic/4.png +0 -0
  30. data/public/images/digits/celtic/5.png +0 -0
  31. data/public/images/digits/celtic/6.png +0 -0
  32. data/public/images/digits/celtic/7.png +0 -0
  33. data/public/images/digits/celtic/8.png +0 -0
  34. data/public/images/digits/celtic/9.png +0 -0
  35. data/public/images/digits/odometer/0.png +0 -0
  36. data/public/images/digits/odometer/1.png +0 -0
  37. data/public/images/digits/odometer/2.png +0 -0
  38. data/public/images/digits/odometer/3.png +0 -0
  39. data/public/images/digits/odometer/4.png +0 -0
  40. data/public/images/digits/odometer/5.png +0 -0
  41. data/public/images/digits/odometer/6.png +0 -0
  42. data/public/images/digits/odometer/7.png +0 -0
  43. data/public/images/digits/odometer/8.png +0 -0
  44. data/public/images/digits/odometer/9.png +0 -0
  45. data/public/images/digits/scout/0.png +0 -0
  46. data/public/images/digits/scout/1.png +0 -0
  47. data/public/images/digits/scout/2.png +0 -0
  48. data/public/images/digits/scout/3.png +0 -0
  49. data/public/images/digits/scout/4.png +0 -0
  50. data/public/images/digits/scout/5.png +0 -0
  51. data/public/images/digits/scout/6.png +0 -0
  52. data/public/images/digits/scout/7.png +0 -0
  53. data/public/images/digits/scout/8.png +0 -0
  54. data/public/images/digits/scout/9.png +0 -0
  55. data/spec/lib/hit_counter_spec.rb +103 -71
  56. data/spec/spec_helper.rb +47 -6
  57. data.tar.gz.sig +0 -0
  58. metadata +106 -110
  59. metadata.gz.sig +0 -0
  60. data/.ruby-version +0 -1
  61. data/.travis.yml +0 -4
  62. data/Gemfile.lock +0 -74
  63. data/README.rdoc +0 -84
  64. data/public/images/digits/celtic/0.gif +0 -0
  65. data/public/images/digits/celtic/1.gif +0 -0
  66. data/public/images/digits/celtic/2.gif +0 -0
  67. data/public/images/digits/celtic/3.gif +0 -0
  68. data/public/images/digits/celtic/4.gif +0 -0
  69. data/public/images/digits/celtic/5.gif +0 -0
  70. data/public/images/digits/celtic/6.gif +0 -0
  71. data/public/images/digits/celtic/7.gif +0 -0
  72. data/public/images/digits/celtic/8.gif +0 -0
  73. data/public/images/digits/celtic/9.gif +0 -0
  74. data/public/images/digits/odometer/0.gif +0 -0
  75. data/public/images/digits/odometer/1.gif +0 -0
  76. data/public/images/digits/odometer/2.gif +0 -0
  77. data/public/images/digits/odometer/3.gif +0 -0
  78. data/public/images/digits/odometer/4.gif +0 -0
  79. data/public/images/digits/odometer/5.gif +0 -0
  80. data/public/images/digits/odometer/6.gif +0 -0
  81. data/public/images/digits/odometer/7.gif +0 -0
  82. data/public/images/digits/odometer/8.gif +0 -0
  83. data/public/images/digits/odometer/9.gif +0 -0
  84. data/public/images/digits/scout/0.gif +0 -0
  85. data/public/images/digits/scout/1.gif +0 -0
  86. data/public/images/digits/scout/2.gif +0 -0
  87. data/public/images/digits/scout/3.gif +0 -0
  88. data/public/images/digits/scout/4.gif +0 -0
  89. data/public/images/digits/scout/5.gif +0 -0
  90. data/public/images/digits/scout/6.gif +0 -0
  91. data/public/images/digits/scout/7.gif +0 -0
  92. data/public/images/digits/scout/8.gif +0 -0
  93. data/public/images/digits/scout/9.gif +0 -0
data/lib/hit_counter.rb CHANGED
@@ -1,148 +1,144 @@
1
- # Copyright (c) 2011 Roderick Monje
2
- #
3
- # This program is free software: you can redistribute it and/or modify
4
- # it under the terms of the GNU General Public License as published by
5
- # the Free Software Foundation, either version 3 of the License, or
6
- # (at your option) any later version.
7
- #
8
- # This program is distributed in the hope that it will be useful,
9
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- # GNU General Public License for more details.
12
- #
13
- # You should have received a copy of the GNU General Public License
14
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
1
+ # Copyright the HitCounter contributors.
2
+ # SPDX-License-Identifier: MIT
3
+ # frozen_string_literal: true
4
+
15
5
  require 'rubygems'
16
6
  require 'bundler/setup'
17
7
  Bundler.require :default
18
8
 
9
+ # Self-hosted Ruby version of that old 90s chestnut, <BLINK>the web-site hit counter</BLINK>
10
+ #
11
+ # @example
12
+ # hc = HitCounter.get 'cnn.com'
13
+ # hc.increment
19
14
  class HitCounter
20
15
  include Mongoid::Document
21
16
  include Mongoid::Timestamps
22
17
 
23
- # Mongo Config ===================================================================================
18
+ # Mongo Config ===============================================================
19
+ field :hits, type: Integer, default: 0
24
20
  field :url
25
- field :hits, :type => Integer, :default => 0
26
21
 
27
22
  # Validates the <code>HitCounter</code>'s URL.
28
23
  #
29
- # If the URI library can parse the value and the scheme is valid, then we assume the url is valid.
24
+ # If the URI library can parse the value and the scheme is valid, then we
25
+ # assume the url is valid.
30
26
  class UrlValidator < ActiveModel::EachValidator
31
- def validate_each record, attribute, value
32
- begin
33
- uri = Addressable::URI.parse value
34
-
35
- if !['http', 'https'].include? uri.scheme
36
- raise Addressable::URI::InvalidURIError
37
- end
38
- rescue Addressable::URI::InvalidURIError
39
- record.errors[attribute] << 'Invalid URL'
40
- end
27
+ private
28
+
29
+ def validate_each(record, attribute, value)
30
+ uri = Addressable::URI.parse value
31
+ raise Addressable::URI::InvalidURIError unless %w[http https].include?(
32
+ uri.scheme
33
+ )
34
+ rescue Addressable::URI::InvalidURIError
35
+ record.errors.add attribute, 'Invalid URL'
41
36
  end
42
37
  end
43
38
 
44
- validates :url, :presence => true, :url => true, :uniqueness => true
39
+ validates :hits, numericality: { only_integer: true }
40
+ validates :url, presence: true, url: true, uniqueness: true
41
+
42
+ # Class methods ==============================================================
45
43
 
46
- # Class methods ==================================================================================
44
+ # Returns a <code>HitCounter</code> matching the specified URL. The HitCounter
45
+ # is created if no matching one is found. In the latter case, the hits
46
+ # argument specifies the starting count.
47
+ #
48
+ # @param url [String] the URL for the site being counted
49
+ # @param hits [Integer] the number of hits to start with
50
+ # @return [HitCounter] the site's HitCounter
51
+ # @example
52
+ # hc = HitCounter.get 'cnn.com'
53
+ # hc = HitCounter.get 'cnn.com', 100
54
+ def self.get(url, hits = 0)
55
+ args = { url: normalize_url(url) }
56
+ args[:hits] = hits unless where(conditions: args).exists?
57
+ find_or_create_by args
58
+ end
47
59
 
48
- # Returns a <code>HitCounter</code> matching the specified URL. The HitCounter is created if no
49
- # matching one is found. In the latter case, the hits argument specifies the starting count.
60
+ # Installs the required Mongoid configuration and image files.
50
61
  #
51
- # * *Args*
52
- # - +url+ -> the URL for the site being counted
53
- # - +hits+ -> the number of hits to start with
54
- # * *Returns*
55
- # - the site's HitCounter
56
- def self.get url, hits = 0
57
- args = {:url => HitCounter.normalize_url(url)}
58
- args[:hits] = hits unless HitCounter.where(:conditions => args).exists?
59
- self.find_or_create_by args
62
+ # @return true
63
+ # @example
64
+ # HitCounter.install
65
+ def self.install
66
+ puts 'Configuring Mongoid and installing image files...'
67
+ full_gem_path = Gem::Specification.find_by_name('hit_counter').full_gem_path
68
+ system "rsync -ruv #{full_gem_path}/config ."
69
+ system "rsync -ruv #{full_gem_path}/public ."
60
70
  end
61
71
 
62
- # Instance methods: Overrides ====================================================================
72
+ # Instance methods: Overrides ================================================
63
73
 
64
74
  # Sets the number of hits.
65
75
  #
66
- # * *Args*
67
- # - +value+ -> the number of hits
68
- # * *Returns*
69
- # - the value
70
- def hits= value
76
+ # @param value [Integer] the initial number of hits
77
+ # @return [Integer] the number of hits
78
+ # @example
79
+ # hc.hits = 100
80
+ def hits=(value)
71
81
  self[:hits] = value.to_i
72
82
  end
73
83
 
74
84
  # Sets the URL to be tracked. The http prefix is optional.
75
85
  #
76
- # * *Args*
77
- # - +value+ -> the URL for the site being counted
78
- # * *Returns*
79
- # - the value
80
- def url= value
81
- self[:url] = HitCounter.normalize_url value
86
+ # @param value [String] the URL for the site being counted
87
+ # @return [String] the normalized URL
88
+ # @example
89
+ # hc.url = 'cnn.com'
90
+ def url=(value)
91
+ self[:url] = HitCounter.send(:normalize_url, value)
82
92
  end
83
93
 
84
- # Instance methods ===============================================================================
94
+ # Instance methods ===========================================================
85
95
 
86
96
  # Returns the hit count as a PNG image, using the specified style:
87
97
  # 1 odometer
88
98
  # 2 scout
89
99
  # 3 Celtic
90
100
  #
91
- # * *Args*
92
- # - +style_number+ -> the image style
93
- # * *Returns*
94
- # - the current hit count as a PNG image
95
- def image style_number
96
- image = HitCounter.cat_image self.hits.to_s, HitCounter.normalize_style_number(style_number)
101
+ # @param style_number [String] the image style
102
+ # @return [Magick::Image] the current hit count as a PNG image
103
+ # @example
104
+ # hc.image = 1
105
+ def image(style_number)
106
+ image = HitCounter.send(:cat_image, hits.to_s, HitCounter.send(:normalize_style_number, style_number))
97
107
  image.format = 'png'
98
108
  image
99
109
  end
100
110
 
101
111
  # Increments the hit count and saves the HitCounter.
102
112
  #
103
- # * *Returns*
104
- # - true if the save was successful
113
+ # @return [true] if the save was successful
114
+ # @example
115
+ # hc.increment
105
116
  def increment
106
117
  self.hits += 1
107
- self.save
118
+ save
108
119
  end
109
120
 
110
- private
121
+ # Defines the available image styles as an array. Add yours to the end.
122
+ STYLES = %w[odometer scout celtic].freeze
111
123
 
112
- STYLES = ['odometer', 'scout', 'celtic']
113
-
114
- def self.cat_image number, style_index, images = Magick::ImageList.new
124
+ private_class_method def self.cat_image(number, style_index, images = Magick::ImageList.new)
115
125
  return images.append(false) if number.blank?
116
- HitCounter.cat_image number[1..-1], style_index, images << Magick::Image.read("#{Rails.root}/public/images/digits/#{STYLES[style_index]}/#{number[0..0]}.gif").first
126
+
127
+ cat_image(number[1..-1], style_index, images <<
128
+ Magick::Image.read("#{Rails.root}/public/images/digits/"\
129
+ "#{STYLES[style_index]}/#{number[0..0]}.png").first)
117
130
  end
118
131
 
119
- def self.normalize_style_number value
132
+ private_class_method def self.normalize_style_number(value)
120
133
  value = value.to_i
121
- value -= 1 if value > 0
134
+ value -= 1 if value.positive?
122
135
 
123
- if value >= 0 && value < STYLES.size
124
- return value
125
- else
126
- value % 3
127
- end
136
+ return value if value >= 0 && value < STYLES.size
137
+
138
+ value % 3
128
139
  end
129
140
 
130
- def self.normalize_url value
141
+ private_class_method def self.normalize_url(value)
131
142
  value !~ %r{^http://} ? "http://#{value}" : value
132
143
  end
133
144
  end
134
-
135
- if defined? Rails
136
- class Railtie < Rails::Railtie
137
- rake_tasks do
138
- namespace :hit_counter do
139
- desc 'Install HitCounter into your app.'
140
- task :install do
141
- puts 'Installing required image files...'
142
- system "rsync -ruv #{Gem.searcher.find('hit_counter').full_gem_path}/config ."
143
- system "rsync -ruv #{Gem.searcher.find('hit_counter').full_gem_path}/public ."
144
- end
145
- end
146
- end
147
- end
148
- end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :hit_counter do
4
+ desc 'Install HitCounter into your app.'
5
+ task(:install) { HitCounter.install }
6
+ end
data/lib/version.rb CHANGED
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Self-hosted Ruby version of that old 90s chestnut, <BLINK>the web-site hit counter</BLINK>
1
4
  class HitCounter
2
- VERSION = '0.1.3'.freeze unless defined?(HitCounter::VERSION)
5
+ # This gem's version
6
+ VERSION = '0.1.6' unless defined?(HitCounter::VERSION)
3
7
  end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,118 +1,150 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
1
+ # Copyright the HitCounter contributors.
2
+ # SPDX-License-Identifier: MIT
3
+ # frozen_string_literal: true
2
4
 
5
+ require "#{File.dirname(__FILE__)}/../spec_helper"
6
+
7
+ JAVASCRIPT_HACK = %q(eval("console.log('All your base belong to us!')"))
8
+ # rubocop:disable Metrics/BlockLength
3
9
  describe HitCounter do
4
- before :all do
5
- HitCounter.delete_all
6
- @hit_counter = HitCounter.get 'www.google.com'
7
- end
10
+ before(:all) { described_class.delete_all }
11
+
12
+ subject { described_class.get 'www.google.com' }
8
13
 
9
- describe '#get' do
10
- context 'when existing URL' do
11
- before { @hit_counter2 = HitCounter.get @hit_counter.url, 10 }
14
+ describe '.get' do
15
+ context 'with existing URL' do
16
+ let!(:hit_counter2) { described_class.get subject.url, 10 }
12
17
 
13
- describe 'document count' do
14
- it { expect(HitCounter.count).to eq 1 }
18
+ describe '.count' do
19
+ it { expect(described_class.count).to eq 1 }
15
20
  end
16
21
 
17
22
  context 'with starting count 10' do
18
- describe 'hits' do
19
- it { expect(@hit_counter2.hits).to eq 10 }
23
+ describe '#hits' do
24
+ it { expect(hit_counter2.hits).to eq 10 }
20
25
  end
21
26
  end
22
27
  end
28
+ context 'with new URL' do
29
+ before { described_class.get 'www.cnn.com' }
23
30
 
24
- context 'when new URL' do
25
- before { HitCounter.get 'www.cnn.com' }
26
-
27
- describe 'document count' do
28
- it { expect(HitCounter.count).to eq 2 }
31
+ describe '.count' do
32
+ it { expect(described_class.count).to eq 2 }
29
33
  end
30
34
 
31
35
  context 'with blank starting count' do
32
36
  describe '#hits' do
33
- it { expect(HitCounter.get('www.nytimes.com', nil).hits).to eq 0 }
37
+ it do
38
+ expect(described_class.get('www.nytimes.com', nil).hits).to eq 0
39
+ end
34
40
  end
35
41
  end
36
-
37
42
  context 'with starting count 10' do
38
43
  describe '#hits' do
39
- it { expect(HitCounter.get('online.wsj.com', 10).hits).to eq 10 }
44
+ it { expect(described_class.get('online.wsj.com', 10).hits).to eq 10 }
40
45
  end
41
46
  end
42
47
  end
48
+ context 'with JavaScript' do
49
+ before { described_class.delete_all }
50
+
51
+ subject { described_class.get(JAVASCRIPT_HACK) }
52
+
53
+ it do
54
+ subject.save
55
+ expect(subject).to be_invalid
56
+ end
57
+ end
43
58
  end
59
+ describe '.install' do
60
+ before do
61
+ expect_any_instance_of(Object).to receive(:system).twice.with match(/config|public/)
62
+ end
44
63
 
64
+ it('copies configuration files and images') { described_class.install }
65
+ end
45
66
  describe '#hits' do
46
- subject { @hit_counter.hits }
47
-
48
- it { expect(subject).to eq 0 }
67
+ it { expect(subject.hits).to eq 0 }
49
68
 
50
69
  context 'when incremented' do
51
- before { @hit_counter.increment }
70
+ before { subject.increment }
52
71
 
53
- it { expect(@hit_counter.hits).to eq 1 }
72
+ it { expect(subject.hits).to eq 1 }
54
73
  end
55
74
  end
75
+ describe '#hits=' do
76
+ context 'with JavaScript' do
77
+ before { subject.hits = JAVASCRIPT_HACK }
56
78
 
57
- describe '#image' do
58
- subject { @hit_counter.image '1' }
59
-
60
- it { expect(subject).to be_a Magick::Image }
79
+ it { expect(subject.hits).to eq 0 }
80
+ end
61
81
  end
62
-
63
- describe '#normalize_style_number' do
64
- context 'when nil' do
65
- it { expect(HitCounter.normalize_style_number(nil)).to be_zero }
82
+ describe '#image' do
83
+ context 'with a valid :style_number' do
84
+ it { expect(subject.image('1').filename).to eq "./public/images/digits/odometer/#{subject.hits}.png" }
66
85
  end
67
-
68
- context 'when empty string' do
69
- it { expect(HitCounter.normalize_style_number('')).to be_zero }
86
+ context 'with JavaScript' do
87
+ it {
88
+ expect(subject.image(JAVASCRIPT_HACK).filename).to eq "./public/images/digits/odometer/#{subject.hits}.png"
89
+ }
70
90
  end
71
-
72
- context 'when within range' do
73
- it 'returns 0 for 1' do
74
- expect(HitCounter.normalize_style_number('1')).to eq 0
91
+ end
92
+ describe '#url=' do
93
+ context 'with JavaScript' do
94
+ before do
95
+ subject.url = JAVASCRIPT_HACK
96
+ subject.save
75
97
  end
76
98
 
77
- it 'returns 2 for 3' do
78
- expect(HitCounter.normalize_style_number('3')).to eq 2
79
- end
99
+ it { expect(subject).to be_invalid }
80
100
  end
81
-
82
- context 'when outside range' do
83
- context 'with negative' do
84
- context 'returns 2 for' do
85
- it -1 do
86
- expect(HitCounter.normalize_style_number('-1')).to eq 2
87
- end
88
-
89
- it -31 do
90
- expect(HitCounter.normalize_style_number('-31')).to eq 2
101
+ end
102
+ describe '.normalize_style_number' do
103
+ context 'with nil' do
104
+ it { expect(described_class.send(:normalize_style_number, nil)).to be_zero }
105
+ end
106
+ context 'with empty string' do
107
+ it { expect(described_class.send(:normalize_style_number, '')).to be_zero }
108
+ end
109
+ context 'with JavaScript' do
110
+ it { expect(described_class.send(:normalize_style_number, JAVASCRIPT_HACK)).to be_zero }
111
+ end
112
+ context 'with number in range' do
113
+ {
114
+ '1' => 0,
115
+ '3' => 2
116
+ }.each do |input, output|
117
+ context "with '#{input}'" do
118
+ it do
119
+ expect(described_class.send(:normalize_style_number, input)).to eq output
91
120
  end
92
121
  end
93
122
  end
94
-
95
- context 'with positive' do
96
- context 'returns 0 for' do
97
- it 4 do
98
- expect(HitCounter.normalize_style_number('4')).to eq 0
99
- end
100
-
101
- it 34 do
102
- expect(HitCounter.normalize_style_number('34')).to eq 0
123
+ end
124
+ context 'with number outside range' do
125
+ {
126
+ '-31' => 2,
127
+ '-1' => 2,
128
+ '4' => 0,
129
+ '34' => 0
130
+ }.each do |input, output|
131
+ context "with '#{input}'" do
132
+ it do
133
+ expect(described_class.send(:normalize_style_number, input)).to eq output
103
134
  end
104
135
  end
105
136
  end
106
137
  end
107
138
  end
108
-
109
- describe '#normalize_url' do
110
- context 'with "cnn.com"' do
111
- it { expect(HitCounter.normalize_url('cnn.com')).to eq 'http://cnn.com' }
112
- end
113
-
114
- context 'with "http://www.nytimes.com"' do
115
- it { expect(HitCounter.normalize_url('http://www.nytimes.com')).to eq 'http://www.nytimes.com' }
139
+ describe '.normalize_url' do
140
+ {
141
+ 'cnn.com' => 'http://cnn.com',
142
+ 'http://www.nytimes.com' => 'http://www.nytimes.com'
143
+ }.each do |input, output|
144
+ context "with '#{input}'" do
145
+ it { expect(described_class.send(:normalize_url, input)).to eq output }
146
+ end
116
147
  end
117
148
  end
118
- end
149
+ end
150
+ # rubocop:enable Metrics/BlockLength
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,8 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- $LOAD_PATH.unshift(File.dirname(__FILE__))
1
+ # frozen_string_literal: true
3
2
 
4
3
  require 'simplecov'
5
- SimpleCov.start
6
-
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
6
  require 'addressable/uri'
8
7
  require 'mongoid'
9
8
  require 'RMagick'
@@ -12,11 +11,53 @@ require 'rspec'
12
11
  require 'hit_counter'
13
12
 
14
13
  Mongoid.load! 'config/mongoid.yml', :test
15
- Mongoid.logger = false
14
+ Mongo::Logger.logger.level = ::Logger::WARN
16
15
 
17
16
  # Stub Rails root during tests.
18
17
  module Rails
19
18
  def self.root
20
19
  '.'
21
20
  end
22
- end
21
+ end
22
+
23
+ require 'rake'
24
+
25
+ # load rake tasks
26
+ # https://dev.to/cassidycodes/how-to-test-rake-tasks-with-rspec-without-rails-3mhb
27
+ module TaskFormat
28
+ extend ActiveSupport::Concern
29
+ included do
30
+ let(:task_name) { self.class.top_level_description.sub(/\Arake /, '') }
31
+ let(:tasks) { Rake::Task }
32
+ # Make the Rake task available as `task` in your examples:
33
+ subject(:task) { tasks[task_name] }
34
+ end
35
+ end
36
+
37
+ RSpec.configure do |config|
38
+ config.before(:suite) do
39
+ Dir.glob('lib/tasks/*.rake').each { |r| Rake::DefaultLoader.new.load r }
40
+ end
41
+
42
+ # Tag Rake specs with `:task` metadata or put them in the spec/tasks dir
43
+ config.define_derived_metadata(file_path: %r{/spec/tasks/}) do |metadata|
44
+ metadata[:type] = :task
45
+ end
46
+
47
+ config.include TaskFormat, type: :task
48
+ end
49
+
50
+ # silence output
51
+ RSpec.configure do |config|
52
+ original_stderr = $stderr
53
+ original_stdout = $stdout
54
+ config.before(:all) do
55
+ # Redirect stderr and stdout
56
+ $stderr = File.open(File::NULL, 'w')
57
+ $stdout = File.open(File::NULL, 'w')
58
+ end
59
+ config.after(:all) do
60
+ $stderr = original_stderr
61
+ $stdout = original_stdout
62
+ end
63
+ end
data.tar.gz.sig ADDED
Binary file