qa_server 0.1.99
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.
- 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
|