status_page_ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +25 -0
  3. data/.gitignore +3 -0
  4. data/.rubocop.yml +10 -0
  5. data/Gemfile +14 -0
  6. data/Gemfile.lock +61 -0
  7. data/README.md +53 -0
  8. data/bin/status-page +6 -0
  9. data/lib/status_page_ruby.rb +20 -0
  10. data/lib/status_page_ruby/pages/base.rb +52 -0
  11. data/lib/status_page_ruby/pages/bitbucket.rb +14 -0
  12. data/lib/status_page_ruby/pages/cloudflare.rb +29 -0
  13. data/lib/status_page_ruby/pages/github.rb +19 -0
  14. data/lib/status_page_ruby/pages/rubygems.rb +14 -0
  15. data/lib/status_page_ruby/repositories/status.rb +40 -0
  16. data/lib/status_page_ruby/services/backup_data.rb +15 -0
  17. data/lib/status_page_ruby/services/build_history_table.rb +32 -0
  18. data/lib/status_page_ruby/services/build_log_table.rb +14 -0
  19. data/lib/status_page_ruby/services/build_stats_table.rb +79 -0
  20. data/lib/status_page_ruby/services/pull_statuses.rb +44 -0
  21. data/lib/status_page_ruby/services/restore_data.rb +15 -0
  22. data/lib/status_page_ruby/status.rb +36 -0
  23. data/lib/status_page_ruby/storage.rb +55 -0
  24. data/lib/status_page_ruby/version.rb +3 -0
  25. data/lib/status_page_ruby_cli.rb +76 -0
  26. data/spec/lib/status_page_ruby/pages/bitbucket_spec.rb +39 -0
  27. data/spec/lib/status_page_ruby/pages/cloudflare_spec.rb +64 -0
  28. data/spec/lib/status_page_ruby/pages/github_spec.rb +57 -0
  29. data/spec/lib/status_page_ruby/pages/rubygems_spec.rb +39 -0
  30. data/spec/lib/status_page_ruby/repositories/status_spec.rb +124 -0
  31. data/spec/lib/status_page_ruby/services/backup_data_spec.rb +13 -0
  32. data/spec/lib/status_page_ruby/services/build_history_table_spec.rb +71 -0
  33. data/spec/lib/status_page_ruby/services/build_log_table_spec.rb +43 -0
  34. data/spec/lib/status_page_ruby/services/build_stats_table_spec.rb +72 -0
  35. data/spec/lib/status_page_ruby/services/pull_statuses_spec.rb +30 -0
  36. data/spec/lib/status_page_ruby/services/restore_data_spec.rb +13 -0
  37. data/spec/lib/status_page_ruby/status_spec.rb +65 -0
  38. data/spec/lib/status_page_ruby/storage_spec.rb +134 -0
  39. data/spec/spec_helper.rb +15 -0
  40. data/status_page_ruby.gemspec +22 -0
  41. metadata +139 -0
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe StatusPageRuby::Pages::Rubygems do
4
+ let(:html) { "<html><body><div class='page-status'><div class='status'>#{status}</div></div></body></html>" }
5
+
6
+ before { allow(OpenURI).to receive(:open_uri).with('https://status.rubygems.org/') { html } }
7
+
8
+ describe '#status' do
9
+ subject { described_class.open.status }
10
+
11
+ context 'when success status' do
12
+ let(:status) { 'All Systems Operational' }
13
+
14
+ it { is_expected.to eq('All Systems Operational') }
15
+ end
16
+
17
+ context 'when not success status' do
18
+ let(:status) { 'All is Failed' }
19
+
20
+ it { is_expected.to eq('All is Failed') }
21
+ end
22
+ end
23
+
24
+ describe '#success?' do
25
+ subject { described_class.open.success? }
26
+
27
+ context 'when success status' do
28
+ let(:status) { 'All Systems Operational' }
29
+
30
+ it { is_expected.to be_truthy }
31
+ end
32
+
33
+ context 'when not success status' do
34
+ let(:status) { 'All is Failed' }
35
+
36
+ it { is_expected.to be_falsey }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe StatusPageRuby::Repositories::Status do
4
+ let(:storage) { double }
5
+ let(:repository) { described_class.new(storage) }
6
+
7
+ describe '#exist?' do
8
+ subject { repository.exist?(status) }
9
+ let(:status) { double(record: double) }
10
+
11
+ before { allow(storage).to receive(:include?).with(status.record) { is_include } }
12
+
13
+ context 'when storage includes status record' do
14
+ let(:is_include) { true }
15
+ it { is_expected.to be_truthy }
16
+ end
17
+
18
+ context 'when storage does not include status record' do
19
+ let(:is_include) { false }
20
+ it { is_expected.to be_falsey }
21
+ end
22
+ end
23
+
24
+ describe '#where' do
25
+ subject { repository.where(service: 'a') }
26
+
27
+ context 'when storage is not empty' do
28
+ context 'when service exists' do
29
+ before { allow(storage).to receive(:read) { [%w[a b c]] } }
30
+
31
+ it 'builds statuses' do
32
+ expect(StatusPageRuby::Status).to receive(:new).with('a', 'b', 'c')
33
+ subject
34
+ end
35
+ end
36
+
37
+ context 'when service does not exist' do
38
+ before { allow(storage).to receive(:read) { [%w[x x x]] } }
39
+
40
+ it 'builds statuses' do
41
+ expect(StatusPageRuby::Status).not_to receive(:new)
42
+ subject
43
+ end
44
+ end
45
+ end
46
+
47
+ context 'when storage is empty' do
48
+ before { allow(storage).to receive(:read) { [] } }
49
+
50
+ it 'does not build statuses' do
51
+ expect(StatusPageRuby::Status).not_to receive(:new)
52
+ subject
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#all' do
58
+ subject { repository.all }
59
+
60
+ context 'when storage is not empty' do
61
+ before { allow(storage).to receive(:read) { [%w[a b c]] } }
62
+
63
+ it 'builds statuses' do
64
+ expect(StatusPageRuby::Status).to receive(:new).with('a', 'b', 'c')
65
+ subject
66
+ end
67
+ end
68
+ context 'when storage is empty' do
69
+ before { allow(storage).to receive(:read) { [] } }
70
+
71
+ it 'does not build statuses' do
72
+ expect(StatusPageRuby::Status).not_to receive(:new)
73
+ subject
74
+ end
75
+ end
76
+ end
77
+
78
+ describe '#create' do
79
+ subject { repository.create(status) }
80
+ let(:status) { double(record: double) }
81
+
82
+ before { allow(repository).to receive(:exist?) { status_exists } }
83
+
84
+ context 'when status does not exist' do
85
+ let(:status_exists) { false }
86
+
87
+ it 'triggers write on storage' do
88
+ expect(storage).to receive(:write).with(status.record).once
89
+ subject
90
+ end
91
+ end
92
+
93
+ context 'with status exists' do
94
+ let(:status_exists) { true }
95
+
96
+ it 'does not trigger write on storage' do
97
+ expect(storage).not_to receive(:write)
98
+ subject
99
+ end
100
+ end
101
+ end
102
+
103
+ describe '#create_batch' do
104
+ subject { repository.create_batch(statuses) }
105
+
106
+ context 'with statuses' do
107
+ let(:statuses) { [double(record: double)] }
108
+
109
+ it 'triggers merge on storage' do
110
+ expect(storage).to receive(:merge).with(statuses.map(&:record)).once
111
+ subject
112
+ end
113
+ end
114
+
115
+ context 'with empty statuses' do
116
+ let(:statuses) { [] }
117
+
118
+ it 'does not trigger merge on storage' do
119
+ expect(storage).not_to receive(:merge)
120
+ subject
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe StatusPageRuby::Services::BackupData do
4
+ let(:storage) { double }
5
+ let(:service) { described_class.new(storage) }
6
+
7
+ describe '#call' do
8
+ it 'triggers copy on storage' do
9
+ expect(storage).to receive(:copy).with('test_path').once
10
+ service.call('test_path')
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe StatusPageRuby::Services::BuildHistoryTable do
4
+ let(:data_file_path) { Tempfile.new('data_file_path').path }
5
+ let(:service) do
6
+ described_class.new(
7
+ StatusPageRuby::Repositories::Status.new(
8
+ StatusPageRuby::Storage.new(data_file_path)
9
+ )
10
+ )
11
+ end
12
+
13
+ describe '#call' do
14
+ before do
15
+ File.write(data_file_path, <<-CSV.delete(' '))
16
+ test1,up,Success,1539506590
17
+ test1,down,Failure,1539507591
18
+ test2,up,Success,1539508592
19
+ CSV
20
+ end
21
+
22
+ context 'with service parameter' do
23
+ context 'when service exists' do
24
+ subject { service.call('test1') }
25
+ let(:expected_table) do
26
+ <<-TABLE.gsub(/^ +/, '').strip
27
+ +---------+--------+---------------------+
28
+ | Service | Status | Time |
29
+ +---------+--------+---------------------+
30
+ | test1 | up | 14.10.2018 08:43:10 |
31
+ | test1 | down | 14.10.2018 08:59:51 |
32
+ +---------+--------+---------------------+
33
+ TABLE
34
+ end
35
+
36
+ it { is_expected.to eq(expected_table) }
37
+ end
38
+
39
+ context 'when service does not exists' do
40
+ subject { service.call('test3') }
41
+ let(:expected_table) do
42
+ <<-TABLE.gsub(/^ +/, '').strip
43
+ +---------+--------+------+
44
+ | Service | Status | Time |
45
+ +---------+--------+------+
46
+ +---------+--------+------+
47
+ TABLE
48
+ end
49
+
50
+ it { is_expected.to eq(expected_table) }
51
+ end
52
+ end
53
+
54
+ context 'without service parameter' do
55
+ subject { service.call }
56
+ let(:expected_table) do
57
+ <<-TABLE.gsub(/^ +/, '').strip
58
+ +---------+--------+---------------------+
59
+ | Service | Status | Time |
60
+ +---------+--------+---------------------+
61
+ | test1 | up | 14.10.2018 08:43:10 |
62
+ | test1 | down | 14.10.2018 08:59:51 |
63
+ | test2 | up | 14.10.2018 09:16:32 |
64
+ +---------+--------+---------------------+
65
+ TABLE
66
+ end
67
+
68
+ it { is_expected.to eq(expected_table) }
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe StatusPageRuby::Services::BuildLogTable do
4
+ describe '#call' do
5
+ subject { described_class.new.call(records) }
6
+
7
+ context 'with records' do
8
+ let(:records) do
9
+ [
10
+ StatusPageRuby::Status.new('test1', 'up', 'Success', '1539506590'),
11
+ StatusPageRuby::Status.new('test2', 'up', 'Success', '1539508592')
12
+ ]
13
+ end
14
+
15
+ let(:expected_table) do
16
+ <<-TABLE.gsub(/^ +/, '').strip
17
+ +---------+--------+---------------------+
18
+ | Service | Status | Time |
19
+ +---------+--------+---------------------+
20
+ | test1 | up | 14.10.2018 08:43:10 |
21
+ | test2 | up | 14.10.2018 09:16:32 |
22
+ +---------+--------+---------------------+
23
+ TABLE
24
+ end
25
+
26
+ it { is_expected.to eq(expected_table) }
27
+ end
28
+
29
+ context 'with empty records' do
30
+ let(:records) { [] }
31
+ let(:expected_table) do
32
+ <<-TABLE.gsub(/^ +/, '').strip
33
+ +---------+--------+------+
34
+ | Service | Status | Time |
35
+ +---------+--------+------+
36
+ +---------+--------+------+
37
+ TABLE
38
+ end
39
+
40
+ it { is_expected.to eq(expected_table) }
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe StatusPageRuby::Services::BuildStatsTable do
4
+ let(:data_file_path) { Tempfile.new('data_file_path').path }
5
+ let(:service) do
6
+ described_class.new(
7
+ StatusPageRuby::Repositories::Status.new(
8
+ StatusPageRuby::Storage.new(data_file_path)
9
+ )
10
+ )
11
+ end
12
+
13
+ describe '#call' do
14
+ before do
15
+ Timecop.freeze(Time.at(1_539_520_990))
16
+ File.write(data_file_path, <<-CSV.delete(' '))
17
+ test1,up,Success,1539506590
18
+ test1,down,Failure,1539510190
19
+ test1,down,Failure,1539513790
20
+ test2,up,Success,1539519190
21
+ test1,up,Success,1539517390
22
+ CSV
23
+ end
24
+
25
+ context 'with service parameter' do
26
+ context 'when service exists' do
27
+ subject { service.call('test1') }
28
+ let(:expected_table) do
29
+ <<-TABLE.gsub(/^ +/, '').strip
30
+ +---------+----------+-----------+
31
+ | Service | Up since | Down time |
32
+ +---------+----------+-----------+
33
+ | test1 | 1 hours | 2 hours |
34
+ +---------+----------+-----------+
35
+ TABLE
36
+ end
37
+
38
+ it { is_expected.to eq(expected_table) }
39
+ end
40
+
41
+ context 'when service does not exists' do
42
+ subject { service.call('test3') }
43
+ let(:expected_table) do
44
+ <<-TABLE.gsub(/^ +/, '').strip
45
+ +---------+----------+-----------+
46
+ | Service | Up since | Down time |
47
+ +---------+----------+-----------+
48
+ +---------+----------+-----------+
49
+ TABLE
50
+ end
51
+
52
+ it { is_expected.to eq(expected_table) }
53
+ end
54
+ end
55
+
56
+ context 'without service parameter' do
57
+ subject { service.call }
58
+ let(:expected_table) do
59
+ <<-TABLE.gsub(/^ +/, '').strip
60
+ +---------+------------+-----------+
61
+ | Service | Up since | Down time |
62
+ +---------+------------+-----------+
63
+ | test1 | 1 hours | 2 hours |
64
+ | test2 | 30 minutes | 0 minutes |
65
+ +---------+------------+-----------+
66
+ TABLE
67
+ end
68
+
69
+ it { is_expected.to eq(expected_table) }
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe StatusPageRuby::Services::PullStatuses do
4
+ let(:status_repository) { double }
5
+ let(:service) { described_class.new(status_repository) }
6
+
7
+ describe '#call' do
8
+ context 'when there is page classes' do
9
+ let(:page_class) { double(open: page) }
10
+ let(:page) { double(class: double(name: 'TestPage'), success?: true, status: 'Success', time: 123) }
11
+ let(:status) { double }
12
+ before { allow(service).to receive(:page_classes) { [page_class] } }
13
+
14
+ it 'does not trigger create_batch for status_repository' do
15
+ expect(status_repository).to receive(:create_batch).with([status]).once
16
+ expect(StatusPageRuby::Status).to receive(:new).with('TestPage', 'up', 'Success', 123) { status }.once
17
+ service.call
18
+ end
19
+ end
20
+
21
+ context 'when there is no page classes' do
22
+ before { allow(service).to receive(:page_class?) { false } }
23
+
24
+ it 'does not trigger create_batch for status_repository' do
25
+ expect(status_repository).not_to receive(:create_batch)
26
+ service.call
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe StatusPageRuby::Services::RestoreData do
4
+ let(:storage) { double }
5
+ let(:service) { described_class.new(storage) }
6
+
7
+ describe '#call' do
8
+ it 'triggers restore on storage' do
9
+ expect(storage).to receive(:restore).with('test_path').once
10
+ service.call('test_path')
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe StatusPageRuby::Status do
4
+ describe '.new' do
5
+ [
6
+ [nil, nil, nil, nil],
7
+ ['', '', '', ''],
8
+ [1, 2, 2, 3],
9
+ ['Github', 'up', 'All Good', 1_539_506_590]
10
+ ].each do |service, state, status, time|
11
+ context "with service: #{service}, state: #{state}, status: #{status} and time: #{time}" do
12
+ subject { described_class.new(service, state, status, time) }
13
+
14
+ it { expect(subject.service).to eq(service.to_s) }
15
+ it { expect(subject.state).to eq(state.to_s) }
16
+ it { expect(subject.time).to eq(time.to_s) }
17
+ end
18
+ end
19
+ end
20
+
21
+ describe '#record' do
22
+ [
23
+ [nil, nil, nil, nil],
24
+ ['', '', '', ''],
25
+ [1, 2, 3, 4],
26
+ ['Github', 'up', 'All Good', 1_539_506_590]
27
+ ].each do |service, state, status, time|
28
+ context "with service: #{service}, state: #{state}, status: #{status} and time: #{time}" do
29
+ subject { described_class.new(service, state, status, time).record }
30
+
31
+ it { is_expected.to eq([service.to_s, state.to_s, status.to_s, time.to_s]) }
32
+ end
33
+ end
34
+ end
35
+
36
+ describe '#history_record' do
37
+ [
38
+ [[nil, nil, nil, 1_539_506_590], ['', '', '14.10.2018 08:43:10']],
39
+ [['', '', '', 1_539_506_590], ['', '', '14.10.2018 08:43:10']],
40
+ [[1, 2, 3, 1_539_506_590], ['1', '2', '14.10.2018 08:43:10']],
41
+ [['Github', 'up', 'All Good', 1_539_506_590], ['Github', 'up', '14.10.2018 08:43:10']]
42
+ ].each do |args, result|
43
+ context "with service: #{args[0]}, state: #{args[1]}, status: #{args[2]} and time: #{args[3]}" do
44
+ subject { described_class.new(*args).history_record }
45
+
46
+ it { is_expected.to eq(result) }
47
+ end
48
+ end
49
+ end
50
+
51
+ describe '#to_csv' do
52
+ [
53
+ [[nil, nil, nil, nil], "\"\",\"\",\"\",\"\"\n"],
54
+ [['', '', '', ''], "\"\",\"\",\"\",\"\"\n"],
55
+ [[1, 2, 3, 4], "1,2,3,4\n"],
56
+ [['Github', 'up', 'All Good', 1_539_506_590], "Github,up,All Good,1539506590\n"]
57
+ ].each do |args, result|
58
+ context "with service: #{args[0]}, state: #{args[1]}, status: #{args[2]} and time: #{args[3]}" do
59
+ subject { described_class.new(*args).to_csv }
60
+
61
+ it { is_expected.to eq(result) }
62
+ end
63
+ end
64
+ end
65
+ end