qa_server 0.1.99
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +71 -0
- data/Gemfile +55 -0
- data/Gemfile.lock +411 -0
- data/LICENSE +201 -0
- data/README.md +187 -0
- data/Rakefile +18 -0
- data/app/assets/images/qa_server/LD4L-bg.png +0 -0
- data/app/assets/images/qa_server/cornell-reduced-white.svg +160 -0
- data/app/assets/images/qa_server/iowa-logo.png +0 -0
- data/app/assets/images/qa_server/samvera-fall-font1-1000w-light.png +0 -0
- data/app/assets/javascripts/qa_server.js +0 -0
- data/app/assets/stylesheets/qa_server/_authorities.scss +0 -0
- data/app/assets/stylesheets/qa_server/_check-status.scss +72 -0
- data/app/assets/stylesheets/qa_server/_footer.scss +20 -0
- data/app/assets/stylesheets/qa_server/_header.scss +51 -0
- data/app/assets/stylesheets/qa_server/_home-page.scss +15 -0
- data/app/assets/stylesheets/qa_server/_monitor-status.scss +13 -0
- data/app/assets/stylesheets/qa_server/_qa_server.scss +36 -0
- data/app/assets/stylesheets/qa_server/_styles.scss +27 -0
- data/app/assets/stylesheets/qa_server/_usage.scss +0 -0
- data/app/controllers/qa_server/authority_list_controller.rb +14 -0
- data/app/controllers/qa_server/authority_validation_controller.rb +77 -0
- data/app/controllers/qa_server/check_status_controller.rb +38 -0
- data/app/controllers/qa_server/homepage_controller.rb +8 -0
- data/app/controllers/qa_server/monitor_status_controller.rb +79 -0
- data/app/controllers/qa_server/usage_controller.rb +8 -0
- data/app/loggers/qa_server/scenario_logger.rb +84 -0
- data/app/models/qa_server/authority_scenario.rb +35 -0
- data/app/models/qa_server/authority_status.rb +18 -0
- data/app/models/qa_server/authority_status_failure.rb +7 -0
- data/app/models/qa_server/scenarios.rb +71 -0
- data/app/models/qa_server/search_scenario.rb +58 -0
- data/app/models/qa_server/term_scenario.rb +50 -0
- data/app/presenters/qa_server/authority_list_presenter.rb +22 -0
- data/app/presenters/qa_server/check_status_presenter.rb +96 -0
- data/app/presenters/qa_server/monitor_status_presenter.rb +108 -0
- data/app/services/qa_server/authority_lister_service.rb +31 -0
- data/app/services/qa_server/authority_loader_service.rb +38 -0
- data/app/services/qa_server/authority_validator_service.rb +41 -0
- data/app/services/qa_server/database_migrator.rb +70 -0
- data/app/services/qa_server/scenarios_loader_service.rb +57 -0
- data/app/validators/qa_server/scenario_validator.rb +134 -0
- data/app/validators/qa_server/search_scenario_validator.rb +84 -0
- data/app/validators/qa_server/term_scenario_validator.rb +42 -0
- data/app/views/layouts/qa_server.html.erb +65 -0
- data/app/views/qa_server/authority_list/index.html.erb +27 -0
- data/app/views/qa_server/check_status/index.html.erb +104 -0
- data/app/views/qa_server/homepage/index.html.erb +10 -0
- data/app/views/qa_server/monitor_status/index.html.erb +78 -0
- data/app/views/qa_server/usage/index.html.erb +106 -0
- data/app/views/shared/_footer.html.erb +24 -0
- data/config/locales/qa_server.en.yml +68 -0
- data/config/routes.rb +12 -0
- data/lib/generators/qa_server/assets_generator.rb +35 -0
- data/lib/generators/qa_server/config_generator.rb +31 -0
- data/lib/generators/qa_server/install_generator.rb +60 -0
- data/lib/generators/qa_server/models_generator.rb +18 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/agrovoc_direct.json +69 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/agrovoc_ld4l_cache.json +85 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/dbpedia_direct.json +36 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/dbpedia_ld4l_cache.json +83 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/geonames_direct.json +68 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/geonames_ld4l_cache.json +102 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_aat_ld4l_cache.json +109 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_tgn_ld4l_cache.json +72 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_ulan_ld4l_cache.json +81 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/loc_direct.json +47 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/locgenres_ld4l_cache.json +99 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/locnames_ld4l_cache.json +89 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/locsubjects_ld4l_cache.json +82 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/mesh_ld4l_cache.json +70 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/nalt_direct.json +32 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/nalt_ld4l_cache.json +84 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/oclcfast_direct.json +81 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/oclcfast_ld4l_cache.json +86 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_direct_validation.yml +9 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_ld4l_cache_validation.yml +9 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_validation.yml +9 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/dbpedia_direct_validation.yml +6 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/dbpedia_ld4l_cache_validation.yml +9 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/geonames_direct_validation.yml +9 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/geonames_ld4l_cache_validation.yml +41 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_aat_ld4l_cache_validation.yml +115 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_tgn_ld4l_cache_validation.yml +9 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_ulan_ld4l_cache_validation.yml +15 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/loc_direct_validation.yml +25 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/loc_validation.yml +22 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locgenres_ld4l_cache_validation.yml +99 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_ld4l_cache_validation.yml +27 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locsubjects_ld4l_cache_validation.yml +27 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/mesh_ld4l_cache_validation.yml +9 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/nalt_direct_validation.yml +6 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/nalt_ld4l_cache_validation.yml +9 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclc_fast_validation.yml +58 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_direct_validation.yml +58 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_ld4l_cache_validation.yml +30 -0
- data/lib/generators/qa_server/templates/config/locales/qa_server.en.yml +9 -0
- data/lib/generators/qa_server/templates/db/migrate/20180313045551_create_cron_authority_status.rb.erb +9 -0
- data/lib/generators/qa_server/templates/db/migrate/20180508045549_rename_cron_authority_status_to_authority_status.rb.erb +5 -0
- data/lib/generators/qa_server/templates/db/migrate/20180508045551_create_authority_status_failure.rb.erb +15 -0
- data/lib/generators/qa_server/templates/qa_server.scss +5 -0
- data/lib/qa_server/engine.rb +19 -0
- data/lib/qa_server/version.rb +3 -0
- data/lib/qa_server.rb +6 -0
- data/lib/tasks/install.rake +8 -0
- data/lib/tasks/qa_server_tasks.rake +4 -0
- data/qa_server.gemspec +39 -0
- data/spec/.gitignore +1 -0
- data/spec/rails_helper.rb +2 -0
- data/spec/spec_helper.rb +283 -0
- data/spec/test_app_templates/Gemfile.extra +5 -0
- data/spec/test_app_templates/lib/generators/test_app_generator.rb +15 -0
- data/tasks/qa_server_dev.rake +16 -0
- metadata +275 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
div.wait-message {
|
2
|
+
display: none;
|
3
|
+
font-family: "Arial", sans-serif;
|
4
|
+
margin-top: 50px;
|
5
|
+
margin-bottom: 50px;
|
6
|
+
margin-left: 90px;
|
7
|
+
margin-right: 90px;
|
8
|
+
border: 1px solid #b30000;
|
9
|
+
padding: 20px;
|
10
|
+
text-align: center;
|
11
|
+
background-color: #ffffe6;
|
12
|
+
color: #4d0000;
|
13
|
+
font-weight: bold;
|
14
|
+
font-size: 1.1em;
|
15
|
+
}
|
16
|
+
|
17
|
+
div#example-url-warning {
|
18
|
+
font-family: "Arial", sans-serif;
|
19
|
+
margin-top: 50px;
|
20
|
+
margin-bottom: 0px;
|
21
|
+
margin-left: 20px;
|
22
|
+
margin-right: 20px;
|
23
|
+
border: 1px solid #b30000;
|
24
|
+
padding: 10px;
|
25
|
+
color: #4d0000;
|
26
|
+
}
|
27
|
+
|
28
|
+
div.status-section {
|
29
|
+
margin-top: 50px;
|
30
|
+
}
|
31
|
+
|
32
|
+
div.validation-types {
|
33
|
+
margin-top: 20px;
|
34
|
+
}
|
35
|
+
|
36
|
+
table {
|
37
|
+
border-collapse: collapse;
|
38
|
+
margin-bottom: 20px;
|
39
|
+
background-color: white;
|
40
|
+
}
|
41
|
+
table, th, td {
|
42
|
+
border: 1px solid darkgray;
|
43
|
+
padding: 5px;
|
44
|
+
}
|
45
|
+
|
46
|
+
th {
|
47
|
+
background-color: #a1b1c4;
|
48
|
+
color: black;
|
49
|
+
}
|
50
|
+
|
51
|
+
td.position {
|
52
|
+
text-align: center;
|
53
|
+
}
|
54
|
+
|
55
|
+
.status-good {
|
56
|
+
text-align: center;
|
57
|
+
background-color: #ccffcc;
|
58
|
+
}
|
59
|
+
|
60
|
+
.status-unknown {
|
61
|
+
text-align: center;
|
62
|
+
background-color: #ffff99;
|
63
|
+
}
|
64
|
+
|
65
|
+
.status-bad {
|
66
|
+
text-align: center;
|
67
|
+
background-color: #ffcccc;
|
68
|
+
}
|
69
|
+
|
70
|
+
label.horizontal-list {
|
71
|
+
padding-right: 15px;
|
72
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
img.footer-logo {
|
2
|
+
margin-top: 12px;
|
3
|
+
margin-bottom: 20px;
|
4
|
+
margin-left: 10px;
|
5
|
+
margin-right: 20px;
|
6
|
+
height: 32px;
|
7
|
+
}
|
8
|
+
|
9
|
+
div.footer-logos {
|
10
|
+
width: 100%;
|
11
|
+
text-align: center;
|
12
|
+
}
|
13
|
+
|
14
|
+
div.footer-logos a {
|
15
|
+
border: none;
|
16
|
+
}
|
17
|
+
|
18
|
+
footer {
|
19
|
+
margin-top: 50px;
|
20
|
+
}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
img.header-logo {
|
2
|
+
float: left;
|
3
|
+
margin-top: 12px;
|
4
|
+
margin-left: 15px;
|
5
|
+
margin-bottom: 8px;
|
6
|
+
height: 64px;
|
7
|
+
}
|
8
|
+
|
9
|
+
/* Banner */
|
10
|
+
.navbar-brand {
|
11
|
+
margin-top: 18px;
|
12
|
+
}
|
13
|
+
|
14
|
+
.institution-name {
|
15
|
+
color: whitesmoke;
|
16
|
+
font-size: 2em;
|
17
|
+
vertical-align: bottom;
|
18
|
+
}
|
19
|
+
|
20
|
+
div.navbar-header {
|
21
|
+
width: 100%;
|
22
|
+
}
|
23
|
+
|
24
|
+
ul.nav-menu, ul.nav-right-menu {
|
25
|
+
list-style-type: none;
|
26
|
+
margin: 0;
|
27
|
+
padding: 0;
|
28
|
+
overflow: hidden;
|
29
|
+
background-color: #222;
|
30
|
+
width: 100%
|
31
|
+
}
|
32
|
+
|
33
|
+
ul.nav-menu li.left-menu {
|
34
|
+
float: left;
|
35
|
+
}
|
36
|
+
|
37
|
+
ul.nav-menu li.right-menu {
|
38
|
+
float: right;
|
39
|
+
}
|
40
|
+
|
41
|
+
ul.nav-menu li a, ul.nav-right-menu li a {
|
42
|
+
display: inline-block;
|
43
|
+
color: lightgrey;
|
44
|
+
text-align: center;
|
45
|
+
padding: 14px 16px;
|
46
|
+
text-decoration: none;
|
47
|
+
}
|
48
|
+
|
49
|
+
ul.nav-menu li a:hover, ul.nav-right-menuli a:hover {
|
50
|
+
background-color: dimgray;
|
51
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
@import 'qa_server/styles', 'qa_server/header', 'qa_server/footer', 'qa_server/home-page', 'qa_server/usage',
|
2
|
+
'qa_server/authorities', 'qa_server/check-status', 'qa_server/monitor-status';
|
3
|
+
|
4
|
+
|
5
|
+
|
6
|
+
//@import 'hydra-editor/multi_value_fields';
|
7
|
+
//@import 'qa_server/variables', 'qa_server/file_sets', 'qa_server/settings', 'qa_server/header',
|
8
|
+
// 'qa_server/styles', 'qa_server/file-listing', 'qa_server/browse_everything_overrides',
|
9
|
+
// 'qa_server/nestable', 'qa_server/collections', 'qa_server/collection_types', 'qa_server/batch-edit',
|
10
|
+
// 'qa_server/home-page', 'qa_server/featured', 'qa_server/usage-stats', 'qa_server/catalog',
|
11
|
+
// 'qa_server/buttons', 'qa_server/tinymce', 'qa_server/proxy-rights', 'qa_server/file-show',
|
12
|
+
// 'qa_server/work-show', 'qa_server/modal', 'qa_server/forms', 'qa_server/form',
|
13
|
+
// 'qa_server/file_manager', 'qa_server/form-progress', 'qa_server/positioning',
|
14
|
+
// 'qa_server/fixedsticky', 'qa_server/file_upload', 'qa_server/representative-media',
|
15
|
+
// 'qa_server/footer', 'qa_server/select_work_type', 'qa_server/users', 'qa_server/dashboard',
|
16
|
+
// 'qa_server/sidebar', 'qa_server/controlled_vocabulary', 'qa_server/accessibility',
|
17
|
+
// 'qa_server/recent', 'qa_server/viewer', 'qa_server/breadcrumbs';
|
18
|
+
//@import 'typeahead';
|
19
|
+
//@import 'sharing_buttons';
|
20
|
+
//
|
21
|
+
///* This class is to workaround an issue in which Bootstrap requires a div to display a tooltip
|
22
|
+
// * on a disabled button. Using a span instead of a div would be ideal but unfortunately it does
|
23
|
+
// * not render the tooltip correctly in all browsers (e.g. in Chrome the tooltip is detected in
|
24
|
+
// * the wrong position). This class forces the div to render inline, just like a span.
|
25
|
+
// *
|
26
|
+
// * More info:
|
27
|
+
// * http://getbootstrap.com/css/#responsive-utilities-classes
|
28
|
+
// * http://stackoverflow.com/a/19938049/446681
|
29
|
+
// */
|
30
|
+
//.visible-all-inline-block {
|
31
|
+
// display: inline-block;
|
32
|
+
//}
|
33
|
+
//
|
34
|
+
//.controlled_vocabulary {
|
35
|
+
// @extend .multi_value;
|
36
|
+
//}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
.container {
|
2
|
+
padding-left: 0px;
|
3
|
+
padding-right: 0px;
|
4
|
+
}
|
5
|
+
|
6
|
+
.ld4l-identity .container {
|
7
|
+
background: #303d4d none repeat scroll 0 0;
|
8
|
+
}
|
9
|
+
|
10
|
+
div#content-wrapper {
|
11
|
+
padding-left: 15px;
|
12
|
+
padding-right: 15px;
|
13
|
+
}
|
14
|
+
|
15
|
+
hr {
|
16
|
+
display: block;
|
17
|
+
height: 1px;
|
18
|
+
border: 0;
|
19
|
+
border-top: 1px solid #ccc;
|
20
|
+
margin: 1em 0;
|
21
|
+
padding: 0;
|
22
|
+
margin-top: 40px;
|
23
|
+
}
|
24
|
+
|
25
|
+
h4 {
|
26
|
+
margin-top: 40px;
|
27
|
+
}
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Controller for Authorities header menu item
|
2
|
+
module QaServer
|
3
|
+
class AuthorityListController < AuthorityValidationController
|
4
|
+
|
5
|
+
class_attribute :presenter_class
|
6
|
+
self.presenter_class = AuthorityListPresenter
|
7
|
+
|
8
|
+
# Sets up presenter with data to display in the UI
|
9
|
+
def index
|
10
|
+
list(authorities_list)
|
11
|
+
@presenter = presenter_class.new(urls_data: status_data_from_log)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module QaServer
|
2
|
+
class AuthorityValidationController < ApplicationController
|
3
|
+
layout 'qa_server'
|
4
|
+
|
5
|
+
attr_reader :status_data
|
6
|
+
|
7
|
+
class_attribute :validator_class,
|
8
|
+
:lister_class,
|
9
|
+
:logger_class
|
10
|
+
|
11
|
+
self.validator_class = AuthorityValidatorService
|
12
|
+
self.lister_class = AuthorityListerService
|
13
|
+
self.logger_class = ScenarioLogger
|
14
|
+
|
15
|
+
VALIDATION_TYPE_PARAM = :validation_type
|
16
|
+
VALIDATE_CONNECTIONS = 'connections'.freeze
|
17
|
+
VALIDATE_ACCURACY = 'accuracy'.freeze
|
18
|
+
ALL_VALIDATIONS = 'all_checks'.freeze
|
19
|
+
DEFAULT_VALIDATION_TYPE = validator_class::VALIDATE_CONNECTIONS
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def status_log
|
24
|
+
@status_log ||= logger_class.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def status_data_from_log
|
28
|
+
@status_data = status_log.to_a
|
29
|
+
end
|
30
|
+
|
31
|
+
def authorities_list
|
32
|
+
@authorities_list ||= lister_class.authorities_list
|
33
|
+
end
|
34
|
+
|
35
|
+
def validate(authorities_list, validation_type = DEFAULT_VALIDATION_TYPE)
|
36
|
+
return if authorities_list.blank?
|
37
|
+
authorities_list.each { |auth_name| validate_authority(auth_name, validation_type) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_authority(auth_name, validation_type)
|
41
|
+
validator_class.run(authority_name: auth_name, validation_type: validation_type, status_log: status_log)
|
42
|
+
end
|
43
|
+
|
44
|
+
def list(authorities_list)
|
45
|
+
return if authorities_list.blank?
|
46
|
+
authorities_list.each { |auth_name| list_scenarios(auth_name) }
|
47
|
+
end
|
48
|
+
|
49
|
+
def list_scenarios(auth_name)
|
50
|
+
lister_class.scenarios_list(authority_name: auth_name, status_log: status_log)
|
51
|
+
end
|
52
|
+
|
53
|
+
def validating_connections?
|
54
|
+
return true if validation_type == VALIDATE_CONNECTIONS || validation_type == ALL_VALIDATIONS
|
55
|
+
false
|
56
|
+
end
|
57
|
+
|
58
|
+
def validating_accuracy?
|
59
|
+
return true if validation_type == VALIDATE_ACCURACY || validation_type == ALL_VALIDATIONS
|
60
|
+
false
|
61
|
+
end
|
62
|
+
|
63
|
+
def validation_type
|
64
|
+
return @validation_type if @validation_type.present?
|
65
|
+
case
|
66
|
+
when params[VALIDATION_TYPE_PARAM] == ALL_VALIDATIONS
|
67
|
+
validator_class::ALL_VALIDATIONS
|
68
|
+
when params[VALIDATION_TYPE_PARAM] == VALIDATE_CONNECTIONS
|
69
|
+
validator_class::VALIDATE_CONNECTIONS
|
70
|
+
when params[VALIDATION_TYPE_PARAM] == VALIDATE_ACCURACY
|
71
|
+
validator_class::VALIDATE_ACCURACY
|
72
|
+
else
|
73
|
+
DEFAULT_VALIDATION_TYPE
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Controller for Check Status header menu item
|
2
|
+
module QaServer
|
3
|
+
class CheckStatusController < AuthorityValidationController
|
4
|
+
|
5
|
+
ALL_AUTHORITIES = '__all__'.freeze
|
6
|
+
|
7
|
+
class_attribute :presenter_class
|
8
|
+
self.presenter_class = CheckStatusPresenter
|
9
|
+
|
10
|
+
# Sets up presenter with data to display in the UI
|
11
|
+
def index
|
12
|
+
validate(authorities_to_validate, validation_type)
|
13
|
+
@presenter = presenter_class.new(authorities_list: authorities_list,
|
14
|
+
connection_status_data: connection_status_data_from_log,
|
15
|
+
accuracy_status_data: accuracy_status_data_from_log)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def connection_status_data_from_log
|
21
|
+
status_log.filter(type: validator_class::VALIDATE_CONNECTIONS)
|
22
|
+
end
|
23
|
+
|
24
|
+
def accuracy_status_data_from_log
|
25
|
+
status_log.filter(type: validator_class::VALIDATE_ACCURACY)
|
26
|
+
end
|
27
|
+
|
28
|
+
def authorities_to_validate
|
29
|
+
return [] unless authority_name.present?
|
30
|
+
(authority_name == ALL_AUTHORITIES) ? authorities_list : [authority_name]
|
31
|
+
end
|
32
|
+
|
33
|
+
def authority_name
|
34
|
+
return @authority_name if @authority_name.present?
|
35
|
+
@authority_name = (params.key? :authority) ? params[:authority].downcase : nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Controller for Monitor Status header menu item
|
2
|
+
module QaServer
|
3
|
+
class MonitorStatusController < AuthorityValidationController
|
4
|
+
|
5
|
+
class_attribute :presenter_class,
|
6
|
+
:authority_status_model_class,
|
7
|
+
:authority_status_failure_model_class
|
8
|
+
|
9
|
+
self.presenter_class = MonitorStatusPresenter
|
10
|
+
self.authority_status_model_class = AuthorityStatus
|
11
|
+
self.authority_status_failure_model_class = AuthorityStatusFailure
|
12
|
+
|
13
|
+
# Sets up presenter with data to display in the UI
|
14
|
+
def index
|
15
|
+
authority_status = latest_authority_status
|
16
|
+
if refresh? || expired_status? || authority_status.blank?
|
17
|
+
validate(authorities_list)
|
18
|
+
status_log.delete_passing
|
19
|
+
update_authority_status
|
20
|
+
authority_status = latest_authority_status
|
21
|
+
end
|
22
|
+
@authority_count = authorities_list.size
|
23
|
+
# TODO: Include historical data too
|
24
|
+
@presenter = presenter_class.new(authority_count: @authority_count,
|
25
|
+
authority_status: @latest_authority_status,
|
26
|
+
current_data: @status_data,
|
27
|
+
historical_data: [])
|
28
|
+
render 'index', :status => :internal_server_error if authority_status.failure_count.positive?
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def latest_authority_status
|
34
|
+
@status_data ||= authority_status_model_class.latest_failures.to_a
|
35
|
+
@latest_authority_status ||= authority_status_model_class.latest
|
36
|
+
end
|
37
|
+
|
38
|
+
def update_authority_status
|
39
|
+
save_authority_status(status_log)
|
40
|
+
@status_data = status_data_from_log
|
41
|
+
end
|
42
|
+
|
43
|
+
def save_authority_status(status_log)
|
44
|
+
@latest_authority_status = authority_status_model_class.create(dt_stamp: dt_stamp_now_et,
|
45
|
+
test_count: status_log.test_count,
|
46
|
+
failure_count: status_log.failure_count)
|
47
|
+
status_log.to_a.each { |failure| save_authority_status_failure(@latest_authority_status, failure) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def save_authority_status_failure(authority_status, failure)
|
51
|
+
authority_status_failure_model_class.create(authority_status_id: authority_status.id,
|
52
|
+
status: failure[:status],
|
53
|
+
status_label: failure[:status_label],
|
54
|
+
authority_name: failure[:authority_name].to_s,
|
55
|
+
subauthority_name: failure[:subauthority_name],
|
56
|
+
service: failure[:service],
|
57
|
+
action: failure[:action],
|
58
|
+
url: failure[:url],
|
59
|
+
err_message: failure[:err_message])
|
60
|
+
end
|
61
|
+
|
62
|
+
def expired_status?
|
63
|
+
status = latest_authority_status
|
64
|
+
status.blank? || status.dt_stamp < yesterday_midnight_et
|
65
|
+
end
|
66
|
+
|
67
|
+
def yesterday_midnight_et
|
68
|
+
(DateTime.yesterday.midnight.to_time + 4.hours).to_datetime.in_time_zone("Eastern Time (US & Canada)")
|
69
|
+
end
|
70
|
+
|
71
|
+
def dt_stamp_now_et
|
72
|
+
Time.now.in_time_zone("Eastern Time (US & Canada)")
|
73
|
+
end
|
74
|
+
|
75
|
+
def refresh?
|
76
|
+
params.key? :refresh
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Provide a log of scenario data and test results
|
2
|
+
module QaServer
|
3
|
+
class ScenarioLogger
|
4
|
+
attr_reader :test_count, :failure_count
|
5
|
+
|
6
|
+
PASS = ScenarioValidator::PASS
|
7
|
+
FAIL = ScenarioValidator::FAIL
|
8
|
+
UNKNOWN = ScenarioValidator::UNKNOWN
|
9
|
+
|
10
|
+
def initialize(test_count = 0, failure_count = 0)
|
11
|
+
@log = []
|
12
|
+
@test_count = test_count
|
13
|
+
@failure_count = failure_count
|
14
|
+
end
|
15
|
+
|
16
|
+
# Add a scenario to the log
|
17
|
+
# @param authority_name [String] name of the authority the scenario was run against
|
18
|
+
# @param status [Symbol] indicating whether the scenario passed, failed, or has unknown status (see PASS, FAIL, UNKNOWN constants)
|
19
|
+
# @param validation_type [Symbol] the type of validation this status data describes (e.g. :connection, :accuracy)
|
20
|
+
# @param subauth [String] name of the subauthority the scenario was run against
|
21
|
+
# @param service [String] identifies the primary service provider (e.g. 'ld4l_cache', 'direct', etc.)
|
22
|
+
# @param action [String] type of scenario (i.e. 'term', 'search')
|
23
|
+
# @param url [String] example url that was used to test a specific term fetch or search query
|
24
|
+
# @param error_message [String] error message if scenario failed
|
25
|
+
# @param expected [Integer] the expected result (e.g. min size of result OR max position of subject within results)
|
26
|
+
# @param actual [Integer] the actual result (e.g. actual size of results OR actual position of subject within results)
|
27
|
+
# @param target [String] the expected target that was validated (e.g. subject_uri for query, pref label for term fetch)
|
28
|
+
def add(authority_name:, validation_type: '', status:, subauth: '', service: '', action: '', url: '', error_message: '', expected: nil, actual: nil, target: nil)
|
29
|
+
@test_count += 1
|
30
|
+
case status
|
31
|
+
when PASS
|
32
|
+
status_label = '√'
|
33
|
+
when UNKNOWN
|
34
|
+
status_label = '?'
|
35
|
+
@failure_count += 1
|
36
|
+
when FAIL
|
37
|
+
status_label = 'X'
|
38
|
+
@failure_count += 1
|
39
|
+
end
|
40
|
+
@log << { type: validation_type,
|
41
|
+
status: status,
|
42
|
+
status_label: status_label,
|
43
|
+
authority_name: authority_name,
|
44
|
+
subauthority_name: subauth,
|
45
|
+
service: service,
|
46
|
+
action: action,
|
47
|
+
url: url,
|
48
|
+
expected: expected,
|
49
|
+
actual: actual,
|
50
|
+
target: target,
|
51
|
+
err_message: error_message }
|
52
|
+
end
|
53
|
+
|
54
|
+
# Delete from the log any tests that passed.
|
55
|
+
def delete_passing
|
56
|
+
@log.delete_if { |entry| entry[:status] == PASS }
|
57
|
+
end
|
58
|
+
|
59
|
+
# Append a log to this log.
|
60
|
+
# @param [ScenarioLog] the log to append to this log
|
61
|
+
def append(other)
|
62
|
+
return unless other.present?
|
63
|
+
@log += other.to_a
|
64
|
+
@test_count += other.test_count
|
65
|
+
@failure_count += other.failure_count
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return selected scenario test results data as an array limited to the specified type or all scenarios if type is nil
|
69
|
+
def filter(type: nil)
|
70
|
+
return @log if type.blank?
|
71
|
+
@log.select { |entry| entry[:type] == type }
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return the scenario test results data as an array
|
75
|
+
def to_a
|
76
|
+
@log
|
77
|
+
end
|
78
|
+
|
79
|
+
# @return the number of scenarios recorded in the log
|
80
|
+
def size
|
81
|
+
to_a.size
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Abstract class that parses the authority configuration from the yml file into the parts needed by inheriting scenario types.
|
2
|
+
module QaServer
|
3
|
+
class AuthorityScenario
|
4
|
+
|
5
|
+
# @return [Qa::Authorities::LinkedData::GenericAuthority] authority instance the scenarios run against
|
6
|
+
attr_reader :authority
|
7
|
+
|
8
|
+
# @return [String] name of the authority the scenarios run against (e.g. 'agrovoc_direct')
|
9
|
+
attr_reader :authority_name
|
10
|
+
|
11
|
+
# @return [String] identifies the primary service provider (e.g. 'ld4l_cache', 'direct', etc.)
|
12
|
+
attr_reader :service
|
13
|
+
|
14
|
+
# @return [String] name of the subauthority the scenario runs against
|
15
|
+
attr_reader :subauthority_name
|
16
|
+
|
17
|
+
# @return [Integer] the minimum size of data that must be returned for the scenario to be considered passing
|
18
|
+
attr_reader :min_result_size
|
19
|
+
|
20
|
+
DEFAULT_SUBAUTH = nil
|
21
|
+
MIN_EXPECTED_SIZE = 200
|
22
|
+
|
23
|
+
# @param authority [Qa::Authorities::LinkedData::GenericAuthority] the instance of the QA authority
|
24
|
+
# @param authoity_name [String] the name of the authority the scenario tests (e.g. "agrovoc_direct")
|
25
|
+
# @param authority_scenario_config [Hash] configurations from the yml file that pertain to all scenarios regardless of type
|
26
|
+
# @param scenario_config [Hash] configuration from the yml file that are specific to a type of scenario
|
27
|
+
def initialize(authority:, authority_name:, authority_scenario_config:, scenario_config: nil)
|
28
|
+
@authority = authority
|
29
|
+
@authority_name = authority_name
|
30
|
+
@service = authority_scenario_config['service']
|
31
|
+
@subauthority_name = DEFAULT_SUBAUTH
|
32
|
+
@min_result_size = MIN_EXPECTED_SIZE
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Provide access to the authority_status database table which tracks a summary of status data over time.
|
2
|
+
module QaServer
|
3
|
+
class AuthorityStatus < ActiveRecord::Base
|
4
|
+
self.table_name = 'authority_status'
|
5
|
+
has_many :authority_status_failure, foreign_key: :authority_status_id
|
6
|
+
|
7
|
+
# Get the latest saved status.
|
8
|
+
def self.latest
|
9
|
+
last
|
10
|
+
end
|
11
|
+
|
12
|
+
# Get the latest set of failures, if any.
|
13
|
+
def self.latest_failures
|
14
|
+
return nil if latest.blank?
|
15
|
+
AuthorityStatusFailure.where(authority_status_id: latest.id)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|