datadog_backup 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,11 +6,10 @@ require 'yaml'
6
6
  require 'deepsort'
7
7
 
8
8
  module DatadogBackup
9
+ ##
10
+ # Meant to be mixed into DatadogBackup::Core
11
+ # Relies on @options[:backup_dir] and @options[:output_format]
9
12
  module LocalFilesystem
10
- ##
11
- # Meant to be mixed into DatadogBackup::Core
12
- # Relies on @options[:backup_dir] and @options[:output_format]
13
-
14
13
  def all_files
15
14
  ::Dir.glob(::File.join(backup_dir, '**', '*')).select { |f| ::File.file?(f) }
16
15
  end
@@ -46,7 +45,7 @@ module DatadogBackup
46
45
  end
47
46
 
48
47
  def file_type(filepath)
49
- ::File.extname(filepath).strip.downcase[1..-1].to_sym
48
+ ::File.extname(filepath).strip.downcase[1..].to_sym
50
49
  end
51
50
 
52
51
  def find_file_by_id(id)
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatadogBackup
4
+ # Monitor specific overrides for backup and restore.
4
5
  class Monitors < Core
5
- def all_monitors
6
- @all_monitors ||= get_all
6
+ def all
7
+ get_all
7
8
  end
8
9
 
9
10
  def api_version
@@ -15,14 +16,14 @@ module DatadogBackup
15
16
  end
16
17
 
17
18
  def backup
18
- all_monitors.map do |monitor|
19
+ all.map do |monitor|
19
20
  id = monitor['id']
20
21
  write_file(dump(get_by_id(id)), filename(id))
21
22
  end
22
23
  end
23
24
 
24
25
  def get_by_id(id)
25
- monitor = all_monitors.select { |monitor| monitor['id'].to_s == id.to_s }.first
26
+ monitor = all.select { |m| m['id'].to_s == id.to_s }.first
26
27
  monitor.nil? ? {} : except(monitor)
27
28
  end
28
29
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatadogBackup
4
+ # Describes what the user wants to see done.
4
5
  module Options
5
6
  def action
6
7
  @options[:action]
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatadogBackup
4
+ # Synthetic specific overrides for backup and restore.
5
+ class Synthetics < Core
6
+ def all
7
+ get_all.fetch('tests')
8
+ end
9
+
10
+ def api_version
11
+ 'v1'
12
+ end
13
+
14
+ def api_resource_name(body = nil)
15
+ return 'synthetics/tests' if body.nil?
16
+ return 'synthetics/tests' if body['type'].nil?
17
+ return 'synthetics/tests/browser' if body['type'].to_s == 'browser'
18
+ return 'synthetics/tests/api' if body['type'].to_s == 'api'
19
+
20
+ raise "Unknown type #{body['type']}"
21
+ end
22
+
23
+ def id_keyname
24
+ 'public_id'
25
+ end
26
+
27
+ def backup
28
+ all.map do |synthetic|
29
+ id = synthetic[id_keyname]
30
+ get_and_write_file(id)
31
+ end
32
+ end
33
+
34
+ def get_by_id(id)
35
+ synthetic = all.select { |s| s[id_keyname].to_s == id.to_s }.first
36
+ synthetic.nil? ? {} : except(synthetic)
37
+ end
38
+
39
+ def initialize(options)
40
+ super(options)
41
+ @banlist = %w[creator created_at modified_at monitor_id public_id].freeze
42
+ end
43
+
44
+ def create(body)
45
+ create_api_resource_name = api_resource_name(body)
46
+ headers = {}
47
+ response = api_service.post("/api/#{api_version}/#{create_api_resource_name}", body, headers)
48
+ resbody = body_with_2xx(response)
49
+ LOGGER.warn "Successfully created #{resbody.fetch(id_keyname)} in datadog."
50
+ LOGGER.info 'Invalidating cache'
51
+ @get_all = nil
52
+ resbody
53
+ end
54
+
55
+ def update(id, body)
56
+ update_api_resource_name = api_resource_name(body)
57
+ headers = {}
58
+ response = api_service.put("/api/#{api_version}/#{update_api_resource_name}/#{id}", body, headers)
59
+ resbody = body_with_2xx(response)
60
+ LOGGER.warn "Successfully restored #{id} to datadog."
61
+ LOGGER.info 'Invalidating cache'
62
+ @get_all = nil
63
+ resbody
64
+ end
65
+ end
66
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatadogBackup
4
+ # Used by CLI and Dashboards to size thread pool according to available CPU cores.
4
5
  module ThreadPool
5
6
  TPOOL = ::Concurrent::ThreadPoolExecutor.new(
6
7
  min_threads: [2, Concurrent.processor_count].max,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatadogBackup
4
- VERSION = '3.0.0'
4
+ VERSION = '3.1.0'
5
5
  end
@@ -8,12 +8,12 @@ require_relative 'datadog_backup/cli'
8
8
  require_relative 'datadog_backup/core'
9
9
  require_relative 'datadog_backup/dashboards'
10
10
  require_relative 'datadog_backup/monitors'
11
+ require_relative 'datadog_backup/synthetics'
11
12
  require_relative 'datadog_backup/thread_pool'
12
13
  require_relative 'datadog_backup/version'
13
14
  require_relative 'datadog_backup/deprecations'
14
15
  DatadogBackup::Deprecations.check
15
16
 
16
-
17
+ # DatadogBackup is a gem for backing up and restoring Datadog monitors and dashboards.
17
18
  module DatadogBackup
18
19
  end
19
-
data/release.config.js CHANGED
@@ -1,8 +1,7 @@
1
1
  module.exports = {
2
2
  "branches": [
3
3
  '+([0-9])?(.{+([0-9]),x}).x',
4
- 'main',
5
- {name: 'alpha', prerelease: true}
4
+ 'main'
6
5
  ],
7
6
  "plugins": [
8
7
  "@semantic-release/commit-analyzer",
@@ -13,12 +12,6 @@ module.exports = {
13
12
  "changelogFile": "CHANGELOG.md"
14
13
  }
15
14
  ],
16
- [
17
- "semantic-release-rubygem",
18
- {
19
- "gemFileDir": "."
20
- }
21
- ],
22
15
  [
23
16
  "@semantic-release/git",
24
17
  {
@@ -47,8 +47,8 @@ describe DatadogBackup::Cli do
47
47
  dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/deleted.json")
48
48
 
49
49
  stubs.get('/api/v1/dashboard') { all_dashboards }
50
- stubs.get('/api/v1/dashboard/stillthere') {[200, {}, {}]}
51
- stubs.get('/api/v1/dashboard/alsostillthere') {[200, {}, {}]}
50
+ stubs.get('/api/v1/dashboard/stillthere') { respond_with200({}) }
51
+ stubs.get('/api/v1/dashboard/alsostillthere') { respond_with200({}) }
52
52
  end
53
53
 
54
54
  it 'deletes the file locally as well' do
@@ -58,66 +58,81 @@ describe DatadogBackup::Cli do
58
58
  end
59
59
  end
60
60
 
61
- describe '#diffs' do
62
- subject { cli.diffs }
63
-
64
- before do
65
- dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/diffs1.json")
66
- dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/diffs2.json")
67
- dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/diffs3.json")
68
- allow(dashboards).to receive(:get_by_id).and_return({ 'text' => 'diff2' })
69
- end
70
-
71
- it {
72
- expect(subject).to include(
73
- " ---\n id: diffs1\n ---\n-text: diff2\n+text: diff\n",
74
- " ---\n id: diffs3\n ---\n-text: diff2\n+text: diff\n",
75
- " ---\n id: diffs2\n ---\n-text: diff2\n+text: diff\n"
76
- )
77
- }
78
- end
79
-
80
61
  describe '#restore' do
81
- subject { cli.restore }
62
+ subject(:restore) { cli.restore }
82
63
 
83
64
  before do
84
65
  dashboards.write_file('{"text": "diff"}', "#{tempdir}/dashboards/diffs1.json")
85
66
  allow(dashboards).to receive(:get_by_id).and_return({ 'text' => 'diff2' })
67
+ allow(dashboards).to receive(:write_file)
68
+ allow(dashboards).to receive(:update)
86
69
  end
87
70
 
88
71
  example 'starts interactive restore' do
89
72
  allow($stdin).to receive(:gets).and_return('q')
90
73
 
91
- expect { subject }.to(
74
+ expect { restore }.to(
92
75
  output(/\(r\)estore to Datadog, overwrite local changes and \(d\)ownload, \(s\)kip, or \(q\)uit\?/).to_stdout
93
76
  .and(raise_error(SystemExit))
94
77
  )
95
78
  end
96
79
 
97
- example 'restore' do
98
- allow($stdin).to receive(:gets).and_return('r')
99
- expect(dashboards).to receive(:update).with('diffs1', { 'text' => 'diff' })
100
- subject
80
+ context 'when the user chooses to restore' do
81
+ before do
82
+ allow($stdin).to receive(:gets).and_return('r')
83
+ end
84
+
85
+ example 'it restores from disk to server' do
86
+ restore
87
+ expect(dashboards).to have_received(:update).with('diffs1', { 'text' => 'diff' })
88
+ end
101
89
  end
102
90
 
103
- example 'download' do
104
- allow($stdin).to receive(:gets).and_return('d')
105
- expect(dashboards).to receive(:write_file).with(%({\n "text": "diff2"\n}), "#{tempdir}/dashboards/diffs1.json")
106
- subject
91
+ context 'when the user chooses to download' do
92
+ before do
93
+ allow($stdin).to receive(:gets).and_return('d')
94
+ end
95
+
96
+ example 'it writes from server to disk' do
97
+ restore
98
+ expect(dashboards).to have_received(:write_file).with(%({\n "text": "diff2"\n}), "#{tempdir}/dashboards/diffs1.json")
99
+ end
107
100
  end
108
101
 
109
- example 'skip' do
110
- allow($stdin).to receive(:gets).and_return('s')
111
- expect(dashboards).not_to receive(:write_file)
112
- expect(dashboards).not_to receive(:update)
113
- subject
102
+ context 'when the user chooses to skip' do
103
+ before do
104
+ allow($stdin).to receive(:gets).and_return('s')
105
+ end
106
+
107
+ example 'it does not write to disk' do
108
+ restore
109
+ expect(dashboards).not_to have_received(:write_file)
110
+ end
111
+
112
+ example 'it does not update the server' do
113
+ restore
114
+ expect(dashboards).not_to have_received(:update)
115
+ end
114
116
  end
115
117
 
116
- example 'quit' do
117
- allow($stdin).to receive(:gets).and_return('q')
118
- expect(dashboards).not_to receive(:write_file)
119
- expect(dashboards).not_to receive(:update)
120
- expect { subject }.to raise_error(SystemExit)
118
+ context 'when the user chooses to quit' do
119
+ before do
120
+ allow($stdin).to receive(:gets).and_return('q')
121
+ end
122
+
123
+ example 'it exits' do
124
+ expect { restore }.to raise_error(SystemExit)
125
+ end
126
+
127
+ example 'it does not write to disk' do
128
+ restore
129
+ expect(dashboards).not_to have_received(:write_file)
130
+ end
131
+
132
+ example 'it does not update the server' do
133
+ restore
134
+ expect(dashboards).not_to have_received(:update)
135
+ end
121
136
  end
122
137
  end
123
138
  end
@@ -18,11 +18,8 @@ describe DatadogBackup::Core do
18
18
  return core
19
19
  end
20
20
 
21
-
22
-
23
-
24
21
  describe '#diff' do
25
- subject { core.diff('diff') }
22
+ subject(:diff) { core.diff('diff') }
26
23
 
27
24
  before do
28
25
  allow(core).to receive(:get_by_id).and_return({ 'text' => 'diff1', 'extra' => 'diff1' })
@@ -30,13 +27,14 @@ describe DatadogBackup::Core do
30
27
  end
31
28
 
32
29
  it {
33
- expect(subject).to eq <<~EOF
30
+ expect(diff).to eq(<<~EODIFF
34
31
  ---
35
32
  -extra: diff1
36
33
  -text: diff1
37
34
  +extra: diff2
38
35
  +text: diff2
39
- EOF
36
+ EODIFF
37
+ .chomp)
40
38
  }
41
39
  end
42
40
 
@@ -47,11 +45,13 @@ describe DatadogBackup::Core do
47
45
  end
48
46
 
49
47
  describe '#initialize' do
50
- subject { core }
48
+ subject(:mycore) { core }
51
49
 
52
50
  it 'makes the subdirectories' do
53
- expect(FileUtils).to receive(:mkdir_p).with("#{tempdir}/core")
54
- subject
51
+ fileutils = class_double(FileUtils).as_stubbed_const
52
+ allow(fileutils).to receive(:mkdir_p)
53
+ mycore
54
+ expect(fileutils).to have_received(:mkdir_p).with("#{tempdir}/core")
55
55
  end
56
56
  end
57
57
 
@@ -62,25 +62,25 @@ describe DatadogBackup::Core do
62
62
  end
63
63
 
64
64
  describe '#create' do
65
- subject { core.create({ 'a' => 'b' }) }
65
+ subject(:create) { core.create({ 'a' => 'b' }) }
66
66
 
67
67
  example 'it will post /api/v1/dashboard' do
68
68
  allow(core).to receive(:api_version).and_return('v1')
69
69
  allow(core).to receive(:api_resource_name).and_return('dashboard')
70
- stubs.post('/api/v1/dashboard', {'a' => 'b'}) {[200, {}, {'id' => 'whatever-id-abc' }]}
71
- subject
70
+ stubs.post('/api/v1/dashboard', { 'a' => 'b' }) { respond_with200({ 'id' => 'whatever-id-abc' }) }
71
+ create
72
72
  stubs.verify_stubbed_calls
73
73
  end
74
74
  end
75
75
 
76
76
  describe '#update' do
77
- subject { core.update('abc-123-def', { 'a' => 'b' }) }
77
+ subject(:update) { core.update('abc-123-def', { 'a' => 'b' }) }
78
78
 
79
79
  example 'it puts /api/v1/dashboard' do
80
80
  allow(core).to receive(:api_version).and_return('v1')
81
81
  allow(core).to receive(:api_resource_name).and_return('dashboard')
82
- stubs.put('/api/v1/dashboard/abc-123-def', {'a' => 'b'}) {[200, {}, {'id' => 'whatever-id-abc' }]}
83
- subject
82
+ stubs.put('/api/v1/dashboard/abc-123-def', { 'a' => 'b' }) { respond_with200({ 'id' => 'whatever-id-abc' }) }
83
+ update
84
84
  stubs.verify_stubbed_calls
85
85
  end
86
86
 
@@ -88,10 +88,11 @@ describe DatadogBackup::Core do
88
88
  before do
89
89
  allow(core).to receive(:api_version).and_return('v1')
90
90
  allow(core).to receive(:api_resource_name).and_return('dashboard')
91
- stubs.put('/api/v1/dashboard/abc-123-def', {'a' => 'b'}) {[404, {}, {'id' => 'whatever-id-abc' }]}
91
+ stubs.put('/api/v1/dashboard/abc-123-def', { 'a' => 'b' }) { [404, {}, { 'id' => 'whatever-id-abc' }] }
92
92
  end
93
+
93
94
  it 'raises an error' do
94
- expect { subject }.to raise_error(RuntimeError, 'update failed with error 404')
95
+ expect { update }.to raise_error(RuntimeError, 'update failed with error 404')
95
96
  end
96
97
  end
97
98
  end
@@ -100,35 +101,55 @@ describe DatadogBackup::Core do
100
101
  before do
101
102
  allow(core).to receive(:api_version).and_return('api-version-string')
102
103
  allow(core).to receive(:api_resource_name).and_return('api-resource-name-string')
103
- stubs.get('/api/api-version-string/api-resource-name-string/abc-123-def') {[200, {}, {'test' => 'ok' }]}
104
- stubs.get('/api/api-version-string/api-resource-name-string/bad-123-id') {[404, {}, {'error' => 'blahblah_not_found' }]}
104
+ stubs.get('/api/api-version-string/api-resource-name-string/abc-123-def') { respond_with200({ 'test' => 'ok' }) }
105
+ stubs.get('/api/api-version-string/api-resource-name-string/bad-123-id') do
106
+ [404, {}, { 'error' => 'blahblah_not_found' }]
107
+ end
105
108
  allow(core).to receive(:load_from_file_by_id).and_return({ 'load' => 'ok' })
106
109
  end
107
110
 
108
111
  context 'when id exists' do
109
- subject { core.restore('abc-123-def') }
112
+ subject(:restore) { core.restore('abc-123-def') }
110
113
 
111
114
  example 'it calls out to update' do
112
- expect(core).to receive(:update).with('abc-123-def', { 'load' => 'ok' })
113
- subject
115
+ allow(core).to receive(:update)
116
+ restore
117
+ expect(core).to have_received(:update).with('abc-123-def', { 'load' => 'ok' })
114
118
  end
115
119
  end
116
120
 
117
121
  context 'when id does not exist on remote' do
118
- subject { core.restore('bad-123-id') }
122
+ subject(:restore_newly) { core.restore('bad-123-id') }
123
+
124
+ let(:fileutils) { class_double(FileUtils).as_stubbed_const }
119
125
 
120
126
  before do
121
127
  allow(core).to receive(:load_from_file_by_id).and_return({ 'load' => 'ok' })
122
- stubs.put('/api/api-version-string/api-resource-name-string/bad-123-id') {[404, {}, {'error' => 'id not found' }]}
123
- stubs.post('/api/api-version-string/api-resource-name-string', {'load' => 'ok'}) {[200, {}, {'id' => 'my-new-id' }]}
128
+ stubs.put('/api/api-version-string/api-resource-name-string/bad-123-id') do
129
+ [404, {}, { 'error' => 'id not found' }]
130
+ end
131
+ stubs.post('/api/api-version-string/api-resource-name-string', { 'load' => 'ok' }) do
132
+ respond_with200({ 'id' => 'my-new-id' })
133
+ end
134
+ allow(fileutils).to receive(:rm)
135
+ allow(core).to receive(:create).with({ 'load' => 'ok' }).and_return({ 'id' => 'my-new-id' })
136
+ allow(core).to receive(:get_and_write_file)
137
+ allow(core).to receive(:find_file_by_id).with('bad-123-id').and_return('/path/to/bad-123-id.json')
124
138
  end
125
139
 
126
- example 'it calls out to create then saves the new file and deletes the new file' do
127
- expect(core).to receive(:create).with({ 'load' => 'ok' }).and_return({ 'id' => 'my-new-id' })
128
- expect(core).to receive(:get_and_write_file).with('my-new-id')
129
- allow(core).to receive(:find_file_by_id).with('bad-123-id').and_return('/path/to/bad-123-id.json')
130
- expect(FileUtils).to receive(:rm).with('/path/to/bad-123-id.json')
131
- subject
140
+ example 'it calls out to create' do
141
+ restore_newly
142
+ expect(core).to have_received(:create).with({ 'load' => 'ok' })
143
+ end
144
+
145
+ example 'it saves the new file' do
146
+ restore_newly
147
+ expect(core).to have_received(:get_and_write_file).with('my-new-id')
148
+ end
149
+
150
+ example 'it deletes the old file' do
151
+ restore_newly
152
+ expect(fileutils).to have_received(:rm).with('/path/to/bad-123-id.json')
132
153
  end
133
154
  end
134
155
  end
@@ -23,24 +23,6 @@ describe DatadogBackup::Dashboards do
23
23
  'title' => 'foo'
24
24
  }
25
25
  end
26
- let(:all_dashboards) do
27
- [
28
- 200,
29
- {},
30
- {
31
- 'dashboards' => [
32
- dashboard_description
33
- ]
34
- }
35
- ]
36
- end
37
- let(:example_dashboard) do
38
- [
39
- 200,
40
- {},
41
- board_abc_123_def
42
- ]
43
- end
44
26
  let(:board_abc_123_def) do
45
27
  {
46
28
  'graphs' => [
@@ -61,6 +43,8 @@ describe DatadogBackup::Dashboards do
61
43
  'title' => 'example dashboard'
62
44
  }
63
45
  end
46
+ let(:all_dashboards) { respond_with200({ 'dashboards' => [dashboard_description] }) }
47
+ let(:example_dashboard) { respond_with200(board_abc_123_def) }
64
48
 
65
49
  before do
66
50
  stubs.get('/api/v1/dashboard') { all_dashboards }
@@ -71,25 +55,32 @@ describe DatadogBackup::Dashboards do
71
55
  subject { dashboards.backup }
72
56
 
73
57
  it 'is expected to create a file' do
74
- file = double('file')
58
+ file = instance_double(File)
75
59
  allow(File).to receive(:open).with(dashboards.filename('abc-123-def'), 'w').and_return(file)
76
- expect(file).to receive(:write).with(::JSON.pretty_generate(board_abc_123_def.deep_sort))
60
+ allow(file).to receive(:write)
77
61
  allow(file).to receive(:close)
78
62
 
79
63
  dashboards.backup
64
+ expect(file).to have_received(:write).with(::JSON.pretty_generate(board_abc_123_def.deep_sort))
80
65
  end
81
66
  end
82
67
 
83
- describe '#all_dashboards' do
84
- subject { dashboards.all_dashboards }
68
+ describe '#filename' do
69
+ subject { dashboards.filename('abc-123-def') }
70
+
71
+ it { is_expected.to eq("#{tempdir}/dashboards/abc-123-def.json") }
72
+ end
73
+
74
+ describe '#get_by_id' do
75
+ subject { dashboards.get_by_id('abc-123-def') }
85
76
 
86
- it { is_expected.to eq [dashboard_description] }
77
+ it { is_expected.to eq board_abc_123_def }
87
78
  end
88
79
 
89
80
  describe '#diff' do
90
81
  it 'calls the api only once' do
91
82
  dashboards.write_file('{"a":"b"}', dashboards.filename('abc-123-def'))
92
- expect(dashboards.diff('abc-123-def')).to eq(<<~EOF
83
+ expect(dashboards.diff('abc-123-def')).to eq(<<~EODASH
93
84
  ---
94
85
  -description: example dashboard
95
86
  -graphs:
@@ -101,8 +92,8 @@ describe DatadogBackup::Dashboards do
101
92
  - title: example graph
102
93
  -title: example dashboard
103
94
  +a: b
104
- EOF
105
- )
95
+ EODASH
96
+ .chomp)
106
97
  end
107
98
  end
108
99
 
@@ -111,10 +102,4 @@ describe DatadogBackup::Dashboards do
111
102
 
112
103
  it { is_expected.to eq({ a: :b }) }
113
104
  end
114
-
115
- describe '#get_by_id' do
116
- subject { dashboards.get_by_id('abc-123-def') }
117
-
118
- it { is_expected.to eq board_abc_123_def }
119
- end
120
105
  end
@@ -3,7 +3,9 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe DatadogBackup::Deprecations do
6
- let(:logger) { double }
6
+ subject(:check) { described_class.check }
7
+
8
+ let(:logger) { instance_double(Logger) }
7
9
 
8
10
  before do
9
11
  stub_const('LOGGER', logger)
@@ -12,24 +14,20 @@ describe DatadogBackup::Deprecations do
12
14
 
13
15
  %w[2.4.10 2.5.9 2.6.8].each do |ruby_version|
14
16
  describe "#check#{ruby_version}" do
15
- subject { described_class.check }
16
-
17
17
  it 'does warn' do
18
18
  stub_const('RUBY_VERSION', ruby_version)
19
- expect(logger).to receive(:warn).with(/ruby-#{ruby_version} is deprecated./)
20
- subject
19
+ check
20
+ expect(logger).to have_received(:warn).with(/ruby-#{ruby_version} is deprecated./)
21
21
  end
22
22
  end
23
23
  end
24
24
 
25
25
  %w[2.7.4 3.0.4 3.1.2 3.2.0-preview1].each do |ruby_version|
26
26
  describe "#check#{ruby_version}" do
27
- subject { described_class.check }
28
-
29
27
  it 'does not warn' do
30
28
  stub_const('RUBY_VERSION', ruby_version)
31
- expect(logger).to_not receive(:warn).with(/ruby-#{ruby_version} is deprecated./)
32
- subject
29
+ check
30
+ expect(logger).not_to have_received(:warn).with(/ruby-#{ruby_version} is deprecated./)
33
31
  end
34
32
  end
35
33
  end