qa_server 0.1.99

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +71 -0
  3. data/Gemfile +55 -0
  4. data/Gemfile.lock +411 -0
  5. data/LICENSE +201 -0
  6. data/README.md +187 -0
  7. data/Rakefile +18 -0
  8. data/app/assets/images/qa_server/LD4L-bg.png +0 -0
  9. data/app/assets/images/qa_server/cornell-reduced-white.svg +160 -0
  10. data/app/assets/images/qa_server/iowa-logo.png +0 -0
  11. data/app/assets/images/qa_server/samvera-fall-font1-1000w-light.png +0 -0
  12. data/app/assets/javascripts/qa_server.js +0 -0
  13. data/app/assets/stylesheets/qa_server/_authorities.scss +0 -0
  14. data/app/assets/stylesheets/qa_server/_check-status.scss +72 -0
  15. data/app/assets/stylesheets/qa_server/_footer.scss +20 -0
  16. data/app/assets/stylesheets/qa_server/_header.scss +51 -0
  17. data/app/assets/stylesheets/qa_server/_home-page.scss +15 -0
  18. data/app/assets/stylesheets/qa_server/_monitor-status.scss +13 -0
  19. data/app/assets/stylesheets/qa_server/_qa_server.scss +36 -0
  20. data/app/assets/stylesheets/qa_server/_styles.scss +27 -0
  21. data/app/assets/stylesheets/qa_server/_usage.scss +0 -0
  22. data/app/controllers/qa_server/authority_list_controller.rb +14 -0
  23. data/app/controllers/qa_server/authority_validation_controller.rb +77 -0
  24. data/app/controllers/qa_server/check_status_controller.rb +38 -0
  25. data/app/controllers/qa_server/homepage_controller.rb +8 -0
  26. data/app/controllers/qa_server/monitor_status_controller.rb +79 -0
  27. data/app/controllers/qa_server/usage_controller.rb +8 -0
  28. data/app/loggers/qa_server/scenario_logger.rb +84 -0
  29. data/app/models/qa_server/authority_scenario.rb +35 -0
  30. data/app/models/qa_server/authority_status.rb +18 -0
  31. data/app/models/qa_server/authority_status_failure.rb +7 -0
  32. data/app/models/qa_server/scenarios.rb +71 -0
  33. data/app/models/qa_server/search_scenario.rb +58 -0
  34. data/app/models/qa_server/term_scenario.rb +50 -0
  35. data/app/presenters/qa_server/authority_list_presenter.rb +22 -0
  36. data/app/presenters/qa_server/check_status_presenter.rb +96 -0
  37. data/app/presenters/qa_server/monitor_status_presenter.rb +108 -0
  38. data/app/services/qa_server/authority_lister_service.rb +31 -0
  39. data/app/services/qa_server/authority_loader_service.rb +38 -0
  40. data/app/services/qa_server/authority_validator_service.rb +41 -0
  41. data/app/services/qa_server/database_migrator.rb +70 -0
  42. data/app/services/qa_server/scenarios_loader_service.rb +57 -0
  43. data/app/validators/qa_server/scenario_validator.rb +134 -0
  44. data/app/validators/qa_server/search_scenario_validator.rb +84 -0
  45. data/app/validators/qa_server/term_scenario_validator.rb +42 -0
  46. data/app/views/layouts/qa_server.html.erb +65 -0
  47. data/app/views/qa_server/authority_list/index.html.erb +27 -0
  48. data/app/views/qa_server/check_status/index.html.erb +104 -0
  49. data/app/views/qa_server/homepage/index.html.erb +10 -0
  50. data/app/views/qa_server/monitor_status/index.html.erb +78 -0
  51. data/app/views/qa_server/usage/index.html.erb +106 -0
  52. data/app/views/shared/_footer.html.erb +24 -0
  53. data/config/locales/qa_server.en.yml +68 -0
  54. data/config/routes.rb +12 -0
  55. data/lib/generators/qa_server/assets_generator.rb +35 -0
  56. data/lib/generators/qa_server/config_generator.rb +31 -0
  57. data/lib/generators/qa_server/install_generator.rb +60 -0
  58. data/lib/generators/qa_server/models_generator.rb +18 -0
  59. data/lib/generators/qa_server/templates/config/authorities/linked_data/agrovoc_direct.json +69 -0
  60. data/lib/generators/qa_server/templates/config/authorities/linked_data/agrovoc_ld4l_cache.json +85 -0
  61. data/lib/generators/qa_server/templates/config/authorities/linked_data/dbpedia_direct.json +36 -0
  62. data/lib/generators/qa_server/templates/config/authorities/linked_data/dbpedia_ld4l_cache.json +83 -0
  63. data/lib/generators/qa_server/templates/config/authorities/linked_data/geonames_direct.json +68 -0
  64. data/lib/generators/qa_server/templates/config/authorities/linked_data/geonames_ld4l_cache.json +102 -0
  65. data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_aat_ld4l_cache.json +109 -0
  66. data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_tgn_ld4l_cache.json +72 -0
  67. data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_ulan_ld4l_cache.json +81 -0
  68. data/lib/generators/qa_server/templates/config/authorities/linked_data/loc_direct.json +47 -0
  69. data/lib/generators/qa_server/templates/config/authorities/linked_data/locgenres_ld4l_cache.json +99 -0
  70. data/lib/generators/qa_server/templates/config/authorities/linked_data/locnames_ld4l_cache.json +89 -0
  71. data/lib/generators/qa_server/templates/config/authorities/linked_data/locsubjects_ld4l_cache.json +82 -0
  72. data/lib/generators/qa_server/templates/config/authorities/linked_data/mesh_ld4l_cache.json +70 -0
  73. data/lib/generators/qa_server/templates/config/authorities/linked_data/nalt_direct.json +32 -0
  74. data/lib/generators/qa_server/templates/config/authorities/linked_data/nalt_ld4l_cache.json +84 -0
  75. data/lib/generators/qa_server/templates/config/authorities/linked_data/oclcfast_direct.json +81 -0
  76. data/lib/generators/qa_server/templates/config/authorities/linked_data/oclcfast_ld4l_cache.json +86 -0
  77. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_direct_validation.yml +9 -0
  78. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_ld4l_cache_validation.yml +9 -0
  79. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_validation.yml +9 -0
  80. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/dbpedia_direct_validation.yml +6 -0
  81. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/dbpedia_ld4l_cache_validation.yml +9 -0
  82. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/geonames_direct_validation.yml +9 -0
  83. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/geonames_ld4l_cache_validation.yml +41 -0
  84. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_aat_ld4l_cache_validation.yml +115 -0
  85. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_tgn_ld4l_cache_validation.yml +9 -0
  86. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_ulan_ld4l_cache_validation.yml +15 -0
  87. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/loc_direct_validation.yml +25 -0
  88. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/loc_validation.yml +22 -0
  89. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locgenres_ld4l_cache_validation.yml +99 -0
  90. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_ld4l_cache_validation.yml +27 -0
  91. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locsubjects_ld4l_cache_validation.yml +27 -0
  92. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/mesh_ld4l_cache_validation.yml +9 -0
  93. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/nalt_direct_validation.yml +6 -0
  94. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/nalt_ld4l_cache_validation.yml +9 -0
  95. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclc_fast_validation.yml +58 -0
  96. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_direct_validation.yml +58 -0
  97. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_ld4l_cache_validation.yml +30 -0
  98. data/lib/generators/qa_server/templates/config/locales/qa_server.en.yml +9 -0
  99. data/lib/generators/qa_server/templates/db/migrate/20180313045551_create_cron_authority_status.rb.erb +9 -0
  100. data/lib/generators/qa_server/templates/db/migrate/20180508045549_rename_cron_authority_status_to_authority_status.rb.erb +5 -0
  101. data/lib/generators/qa_server/templates/db/migrate/20180508045551_create_authority_status_failure.rb.erb +15 -0
  102. data/lib/generators/qa_server/templates/qa_server.scss +5 -0
  103. data/lib/qa_server/engine.rb +19 -0
  104. data/lib/qa_server/version.rb +3 -0
  105. data/lib/qa_server.rb +6 -0
  106. data/lib/tasks/install.rake +8 -0
  107. data/lib/tasks/qa_server_tasks.rake +4 -0
  108. data/qa_server.gemspec +39 -0
  109. data/spec/.gitignore +1 -0
  110. data/spec/rails_helper.rb +2 -0
  111. data/spec/spec_helper.rb +283 -0
  112. data/spec/test_app_templates/Gemfile.extra +5 -0
  113. data/spec/test_app_templates/lib/generators/test_app_generator.rb +15 -0
  114. data/tasks/qa_server_dev.rake +16 -0
  115. 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,15 @@
1
+ div.page-description {
2
+ padding-bottom: 50px;
3
+ }
4
+
5
+ p.welcome, p.welcome2 {
6
+ padding-top: 50px;
7
+ padding-left: 225px;
8
+ padding-right: 225px;
9
+ font-size: 1.2em;
10
+ text-align: justify;
11
+ }
12
+
13
+ p.welcome2 {
14
+ padding-top: 10px;
15
+ }
@@ -0,0 +1,13 @@
1
+ table.dashboard-status td {
2
+ text-align: center;
3
+ }
4
+
5
+ a.dashboard-refresh {
6
+ margin-left: 20px;
7
+ color: #0088cc;
8
+ }
9
+
10
+ p.status-update-dtstamp {
11
+ color: darkred;
12
+ font-style: italic;
13
+ }
@@ -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,8 @@
1
+ module QaServer
2
+ class HomepageController < ApplicationController
3
+ layout 'qa_server'
4
+
5
+ def index
6
+ end
7
+ end
8
+ 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,8 @@
1
+ module QaServer
2
+ class UsageController < ApplicationController
3
+ layout 'qa_server'
4
+
5
+ def index
6
+ end
7
+ end
8
+ 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
@@ -0,0 +1,7 @@
1
+ # Provide access to the authority_status_failure database table which tracks specific failures over time.
2
+ module QaServer
3
+ class AuthorityStatusFailure < ActiveRecord::Base
4
+ self.table_name = 'authority_status_failure'
5
+ belongs_to :authority_status
6
+ end
7
+ end