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