qa_server 7.4.0 → 7.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop_fixme.yml +7 -0
  3. data/.travis.yml +4 -5
  4. data/CHANGELOG.md +45 -0
  5. data/Rakefile +1 -1
  6. data/app/assets/stylesheets/qa_server/_check-status.scss +36 -0
  7. data/app/cache_processors/qa_server/cache_expiry_service.rb +8 -8
  8. data/app/cache_processors/qa_server/job_id_cache.rb +4 -4
  9. data/app/cache_processors/qa_server/performance_cache.rb +34 -34
  10. data/app/cache_processors/qa_server/performance_day_graph_cache.rb +7 -7
  11. data/app/cache_processors/qa_server/performance_month_graph_cache.rb +7 -7
  12. data/app/cache_processors/qa_server/performance_year_graph_cache.rb +7 -7
  13. data/app/cache_processors/qa_server/scenario_history_cache.rb +7 -7
  14. data/app/cache_processors/qa_server/scenario_history_graph_cache.rb +7 -7
  15. data/app/cache_processors/qa_server/scenario_run_cache.rb +7 -7
  16. data/app/cache_processors/qa_server/scenario_run_failures_cache.rb +7 -7
  17. data/app/cache_processors/qa_server/scenario_run_summary_cache.rb +7 -7
  18. data/app/controllers/concerns/qa_server/authority_validation_behavior.rb +49 -44
  19. data/app/controllers/qa_server/check_status_controller.rb +92 -22
  20. data/app/controllers/qa_server/fetch_controller.rb +36 -36
  21. data/app/controllers/qa_server/monitor_status_controller.rb +106 -84
  22. data/app/jobs/qa_server/history_graph_job.rb +10 -10
  23. data/app/jobs/qa_server/monitor_tests_job.rb +17 -17
  24. data/app/jobs/qa_server/performance_day_graph_job.rb +21 -21
  25. data/app/jobs/qa_server/performance_month_graph_job.rb +21 -21
  26. data/app/jobs/qa_server/performance_per_byte_job.rb +56 -56
  27. data/app/jobs/qa_server/performance_year_graph_job.rb +21 -21
  28. data/app/loggers/qa_server/scenario_logger.rb +74 -4
  29. data/app/models/qa_server/authority_scenario.rb +4 -4
  30. data/app/models/qa_server/authority_status.rb +2 -2
  31. data/app/models/qa_server/authority_status_failure.rb +1 -1
  32. data/app/models/qa_server/performance_history.rb +2 -2
  33. data/app/models/qa_server/scenario_run_history.rb +63 -54
  34. data/app/models/qa_server/scenario_run_registry.rb +2 -2
  35. data/app/models/qa_server/scenarios.rb +26 -26
  36. data/app/models/qa_server/search_scenario.rb +24 -13
  37. data/app/models/qa_server/term_scenario.rb +29 -29
  38. data/app/prepends/prepended_linked_data/find_term.rb +40 -40
  39. data/app/prepends/prepended_linked_data/search_query.rb +36 -36
  40. data/app/prepends/prepended_rdf/rdf_graph.rb +7 -7
  41. data/app/presenters/concerns/qa_server/monitor_status/performance_datatable_behavior.rb +32 -32
  42. data/app/presenters/concerns/qa_server/monitor_status/performance_graph_behavior.rb +64 -64
  43. data/app/presenters/qa_server/check_status_presenter.rb +63 -7
  44. data/app/presenters/qa_server/monitor_status/current_status_presenter.rb +9 -8
  45. data/app/presenters/qa_server/monitor_status/history_presenter.rb +55 -4
  46. data/app/services/concerns/qa_server/gruff_graph.rb +16 -16
  47. data/app/services/qa_server/authority_loader_service.rb +14 -14
  48. data/app/services/qa_server/authority_validator_service.rb +1 -0
  49. data/app/services/qa_server/database_migrator.rb +14 -14
  50. data/app/services/qa_server/history_graphing_service.rb +30 -30
  51. data/app/services/qa_server/performance_calculator_service.rb +80 -80
  52. data/app/services/qa_server/performance_datatable_service.rb +35 -35
  53. data/app/services/qa_server/performance_graph_data_service.rb +27 -27
  54. data/app/services/qa_server/performance_graphing_service.rb +55 -55
  55. data/app/services/qa_server/performance_per_byte_calculator_service.rb +38 -38
  56. data/app/services/qa_server/performance_per_byte_data_service.rb +7 -7
  57. data/app/services/qa_server/scenarios_loader_service.rb +1 -1
  58. data/app/services/qa_server/time_period_service.rb +21 -21
  59. data/app/validators/qa_server/scenario_validator.rb +99 -87
  60. data/app/validators/qa_server/search_scenario_validator.rb +67 -61
  61. data/app/validators/qa_server/term_scenario_validator.rb +20 -15
  62. data/app/views/qa_server/check_status/index.html.erb +120 -24
  63. data/app/views/qa_server/monitor_status/_test_summary.html.erb +1 -1
  64. data/config/i18n-tasks.yml +133 -0
  65. data/config/locales/qa_server.en.yml +21 -5
  66. data/lib/generators/qa_server/assets_generator.rb +4 -4
  67. data/lib/generators/qa_server/templates/config/authorities/linked_data/cerl_ld4l_cache.json +2 -2
  68. data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_aat_ld4l_cache.json +62 -1
  69. data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_tgn_ld4l_cache.json +45 -11
  70. data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_ulan_ld4l_cache.json +104 -8
  71. data/lib/generators/qa_server/templates/config/authorities/linked_data/isni_ld4l_cache.json +90 -0
  72. data/lib/generators/qa_server/templates/config/authorities/linked_data/ligatus_ld4l_cache.json +133 -0
  73. data/lib/generators/qa_server/templates/config/authorities/linked_data/locnames_rwo2_ld4l_cache.json +248 -0
  74. data/lib/generators/qa_server/templates/config/authorities/linked_data/locnames_rwo3_ld4l_cache.json +248 -0
  75. data/lib/generators/qa_server/templates/config/authorities/linked_data/locnames_rwo_ld4l_cache.json +4 -4
  76. data/lib/generators/qa_server/templates/config/authorities/linked_data/locvocabs_ld4l_cache.json +117 -0
  77. data/lib/generators/qa_server/templates/config/authorities/linked_data/mesh_nlm_ld4l_cache.json +135 -3
  78. data/lib/generators/qa_server/templates/config/authorities/linked_data/oclcfast_direct.json +5 -0
  79. data/lib/generators/qa_server/templates/config/authorities/linked_data/oclcfast_ld4l_cache.json +2 -4
  80. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_direct_validation.yml +31 -0
  81. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_ld4l_cache_validation.yml +31 -0
  82. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/cerl_ld4l_cache_validation.yml +24 -12
  83. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/dbpedia_ld4l_cache_validation.yml +33 -0
  84. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/geonames_direct_validation.yml +35 -0
  85. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/geonames_ld4l_cache_validation.yml +55 -5
  86. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_aat_ld4l_cache_validation.yml +253 -0
  87. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_tgn_ld4l_cache_validation.yml +31 -1
  88. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_ulan_ld4l_cache_validation.yml +38 -1
  89. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/isni_ld4l_cache_validation.yml +10 -0
  90. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/ligatus_ld4l_cache_validation.yml +36 -0
  91. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locdemographics_ld4l_cache_validation.yml +69 -44
  92. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locgenres_ld4l_cache_validation.yml +22 -0
  93. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_ld4l_cache_validation.yml +65 -0
  94. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_rwo2_ld4l_cache_validation.yml +78 -0
  95. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_rwo3_ld4l_cache_validation.yml +73 -0
  96. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_rwo_ld4l_cache_validation.yml +71 -3
  97. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locperformance_ld4l_cache_validation.yml +6 -0
  98. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locsubjects_ld4l_cache_validation.yml +30 -0
  99. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locvocabs_ld4l_cache_validation.yml +430 -0
  100. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/mesh_nlm_ld4l_cache_validation.yml +54 -1
  101. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/nalt_ld4l_cache_validation.yml +37 -0
  102. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclc_fast_validation.yml +71 -5
  103. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_direct_validation.yml +73 -2
  104. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_ld4l_cache_validation.yml +73 -0
  105. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/rda_registry_ld4l_cache_validation.yml +307 -0
  106. data/lib/qa_server/configuration.rb +28 -24
  107. data/lib/qa_server/version.rb +1 -1
  108. data/qa_server.gemspec +6 -5
  109. data/spec/feature/accuracy_spec.rb +32 -0
  110. data/spec/i18n_spec.rb +35 -0
  111. data/spec/presenters/qa_server/monitor_status/history_presenter_spec.rb +81 -0
  112. data/spec/spec_helper.rb +4 -0
  113. metadata +65 -17
@@ -8,6 +8,7 @@ module QaServer
8
8
 
9
9
  VALIDATE_CONNECTION = :connection
10
10
  VALIDATE_ACCURACY = :accuracy
11
+ VALIDATE_ACCURACY_COMPARISON = :accuracy_comparison
11
12
  ALL_VALIDATIONS = :all_validations
12
13
  DEFAULT_VALIDATION_TYPE = VALIDATE_CONNECTION
13
14
 
@@ -33,92 +34,103 @@ module QaServer
33
34
  log
34
35
  end
35
36
 
36
- private
37
-
38
- # Log the structure of the scenario and status of a test run.
39
- # @param [Hash] status_info holding information to be logged
40
- # @see QaServer::ScenarioLogger
41
- def log(status_info = {})
42
- status_info[:authority_name] = authority_name
43
- status_info[:validation_type] = scenario_validation_type
44
- status_info[:subauth] = subauthority_name
45
- status_info[:service] = service
46
- status_info[:action] = action
47
- status_info[:url] = url
48
- status_log.add(status_info)
49
- end
50
-
51
- def run_accuracy_scenario
52
- # ABSTRACT - must be implemented by scenario validator for specific types
53
- end
54
-
55
- def run_connection_scenario
56
- # ABSTRACT - must be implemented by scenario validator for specific types
57
- end
58
-
59
- # Runs the test in the block passed by the specific scenario type.
60
- # @return [Symbol] :good (PASS) or :unknown (UNKNOWN) based on whether enough results were returned
61
- def test_connection(min_expected_size: MIN_EXPECTED_SIZE, scenario_type_name:)
62
- dt_start = QaServer::TimeService.current_time
63
- results = yield if block_given?
64
- dt_end = QaServer::TimeService.current_time
65
- actual_size = results.to_s.length
66
- status = actual_size > min_expected_size ? PASS : UNKNOWN
67
- errmsg = status == PASS ? '' : "#{scenario_type_name.capitalize} scenario unknown status; cause: Results actual size (#{actual_size} < expected size (#{min_expected_size})"
68
- log(status: status, error_message: errmsg, normalization_run_time: (dt_end - dt_start)) # TODO: need to get run times from results
69
- rescue Exception => e
70
- dt_end = QaServer::TimeService.current_time
71
- log(status: FAIL, error_message: "Exception executing #{scenario_type_name} scenario; cause: #{e.message}", request_run_time: (dt_end - dt_start))
72
- end
73
-
74
- def authority
75
- scenario.authority
76
- end
77
-
78
- def authority_name
79
- scenario.authority_name.upcase
80
- end
81
-
82
- def subauthority_name
83
- scenario.subauthority_name
84
- end
85
-
86
- def service
87
- scenario.service
88
- end
89
-
90
- def url
91
- scenario.url
92
- end
93
-
94
- def action
95
- # ABSTRACT - must be implemented by scenario validator for specific types
96
- end
97
-
98
- def scenario_validation_type
99
- return VALIDATE_CONNECTION if connection_scenario?
100
- return VALIDATE_ACCURACY if accuracy_scenario?
101
- nil
102
- end
103
-
104
- def validating_connections?
105
- return true if validation_type == VALIDATE_CONNECTION || validation_type == ALL_VALIDATIONS
106
- false
107
- end
108
-
109
- def validating_accuracy?
110
- return true if validation_type == VALIDATE_ACCURACY || validation_type == ALL_VALIDATIONS
111
- false
112
- end
113
-
114
- def accuracy_scenario?
115
- # ABSTRACT define in specific scenario type validator (i.e. QaServer::TermScenarioValidator, QaServer::SearchScenarioValidator)
116
- false
117
- end
118
-
119
- def connection_scenario?
120
- # ABSTRACT define in specific scenario type validator (i.e. QaServer::TermScenarioValidator, QaServer::SearchScenarioValidator)
121
- false
122
- end
37
+ private
38
+
39
+ # Log the structure of the scenario and status of a test run.
40
+ # @param [Hash] status_info holding information to be logged
41
+ # @see QaServer::ScenarioLogger
42
+ def log(status_info = {})
43
+ status_info[:authority_name] = authority_name
44
+ status_info[:validation_type] = scenario_validation_type
45
+ status_info[:subauth] = subauthority_name
46
+ status_info[:service] = service
47
+ status_info[:action] = action
48
+ status_info[:url] = url
49
+ status_info[:request_data] = request_data
50
+ status_log.add(status_info)
51
+ end
52
+
53
+ def run_accuracy_scenario
54
+ # ABSTRACT - must be implemented by scenario validator for specific types
55
+ end
56
+
57
+ def run_connection_scenario
58
+ # ABSTRACT - must be implemented by scenario validator for specific types
59
+ end
60
+
61
+ def request_data
62
+ # ABSTRACT - must be implemented by scenario validator for specific types
63
+ end
64
+
65
+ # Runs the test in the block passed by the specific scenario type.
66
+ # @return [Symbol] :good (PASS) or :unknown (UNKNOWN) based on whether enough results were returned
67
+ def test_connection(min_expected_size: MIN_EXPECTED_SIZE, scenario_type_name:)
68
+ dt_start = QaServer::TimeService.current_time
69
+ results = yield if block_given?
70
+ dt_end = QaServer::TimeService.current_time
71
+ actual_size = results.to_s.length
72
+ status = actual_size > min_expected_size ? PASS : UNKNOWN
73
+ errmsg = status == PASS ? '' : "#{scenario_type_name.capitalize} scenario unknown status; cause: Results actual size (#{actual_size} < expected size (#{min_expected_size})"
74
+ log(status: status, error_message: errmsg, normalization_run_time: (dt_end - dt_start)) # TODO: need to get run times from results
75
+ rescue Exception => e
76
+ dt_end = QaServer::TimeService.current_time
77
+ log(status: FAIL, error_message: "Exception executing #{scenario_type_name} scenario; cause: #{e.message}", request_run_time: (dt_end - dt_start))
78
+ end
79
+
80
+ # @return [Qa::Authorities::LinkedData::GenericAuthority] authority instance the scenarios run against
81
+ def authority
82
+ scenario.authority
83
+ end
84
+
85
+ # @return [Symbol] name of the authority (e.g. :CERL_LD4L_CACHE)
86
+ def authority_name
87
+ scenario.authority_name.upcase
88
+ end
89
+
90
+ # @return [String] name of the subauthority (e.g. "person")
91
+ def subauthority_name
92
+ scenario.subauthority_name
93
+ end
94
+
95
+ # @return [String] service providing the data (e.g. "ld4l_cache" or "direct")
96
+ def service
97
+ scenario.service
98
+ end
99
+
100
+ # @return [String] relative URL with ready to execute (e.g. ""/authorities/search/linked_data/cerl_ld4l_cache/person?q=office")
101
+ def url
102
+ scenario.url
103
+ end
104
+
105
+ # @return [String] action being tested (e.g. "search" or "term")
106
+ def action
107
+ # ABSTRACT - must be implemented by scenario validator for specific types
108
+ end
109
+
110
+ def scenario_validation_type
111
+ return VALIDATE_CONNECTION if connection_scenario?
112
+ return VALIDATE_ACCURACY if accuracy_scenario?
113
+ nil
114
+ end
115
+
116
+ def validating_connections?
117
+ return true if validation_type == VALIDATE_CONNECTION || validation_type == ALL_VALIDATIONS
118
+ false
119
+ end
120
+
121
+ def validating_accuracy?
122
+ return true if [VALIDATE_ACCURACY, VALIDATE_ACCURACY_COMPARISON, ALL_VALIDATIONS].include? validation_type
123
+ false
124
+ end
125
+
126
+ def accuracy_scenario?
127
+ # ABSTRACT define in specific scenario type validator (i.e. QaServer::TermScenarioValidator, QaServer::SearchScenarioValidator)
128
+ false
129
+ end
130
+
131
+ def connection_scenario?
132
+ # ABSTRACT define in specific scenario type validator (i.e. QaServer::TermScenarioValidator, QaServer::SearchScenarioValidator)
133
+ false
134
+ end
123
135
  end
124
136
  end
@@ -6,87 +6,93 @@ module QaServer
6
6
  class SearchScenarioValidator < ScenarioValidator
7
7
  SEARCH_ACTION = 'search'
8
8
 
9
+ # CONCRETE Implementation: Return value of request_data
10
+ attr_reader :request_data
11
+ private :request_data
12
+
9
13
  # @param scenario [SearchScenario] the scenario to run
10
14
  # @param status_log [ScenarioLogger] logger for recording test results
11
15
  # @param validation_type [Symbol] the type of scenarios to run (e.g. VALIDATE_CONNECTION, VALIDATE_ACCURACY, ALL_VALIDATIONS)
12
16
  def initialize(scenario:, status_log:, validation_type: DEFAULT_VALIDATION_TYPE)
13
17
  super
18
+ @request_data = scenario.query
14
19
  end
15
20
 
16
- private
21
+ private
17
22
 
18
- def action
19
- SEARCH_ACTION
20
- end
23
+ def action
24
+ SEARCH_ACTION
25
+ end
21
26
 
22
- # Run the connection test and log results
23
- def run_connection_scenario
24
- test_connection(min_expected_size: scenario.min_result_size, scenario_type_name: 'search') do
25
- replacements = scenario.replacements.dup
26
- authority.search(scenario.query,
27
- subauth: scenario.subauthority_name,
28
- replacements: replacements)
29
- end
27
+ # CONCRETE Implementation: Run the connection test and log results
28
+ def run_connection_scenario
29
+ test_connection(min_expected_size: scenario.min_result_size, scenario_type_name: 'search') do
30
+ replacements = scenario.replacements.dup
31
+ authority.search(scenario.query,
32
+ subauth: scenario.subauthority_name,
33
+ replacements: replacements)
30
34
  end
35
+ end
31
36
 
32
- # Run the accuracy test and log results
33
- def run_accuracy_scenario
34
- test_accuracy(subject_uri: scenario.subject_uri, expected_by_position: scenario.expected_by_position) do
35
- authority.search(scenario.query,
36
- subauth: scenario.subauthority_name,
37
- replacements: scenario.replacements)
38
- end
37
+ # CONCRETE Implementation: Run the accuracy test and log results
38
+ def run_accuracy_scenario
39
+ test_accuracy(subject_uri: scenario.subject_uri, expected_by_position: scenario.expected_by_position, pending: scenario.pending?) do
40
+ replacements = scenario.replacements.dup
41
+ authority.search(scenario.query,
42
+ subauth: scenario.subauthority_name,
43
+ replacements: replacements)
39
44
  end
45
+ end
40
46
 
41
- # Runs the accuracy test and log results
42
- def test_accuracy(subject_uri:, expected_by_position:)
43
- dt_start = QaServer::TimeService.current_time
44
- results = yield if block_given?
45
- dt_end = QaServer::TimeService.current_time
46
- if results.blank?
47
- log(status: UNKNOWN, errmsg: "Search position scenario failed; cause: no results found", expected: expected_by_position, target: subject_uri, request_run_time: (dt_end - dt_start))
48
- return
49
- end
50
-
51
- check_position(results, subject_uri, expected_by_position, total_run_time: (dt_end - dt_start)) # TODO: need to get run times from results
52
- rescue Exception => e
53
- dt_end = QaServer::TimeService.current_time
54
- log(status: FAIL, errmsg: "Exception executing search position scenario; cause: #{e.message}",
55
- expected: expected_by_position, target: subject_uri, request_run_time: (dt_end - dt_start))
47
+ # Runs the accuracy test and log results
48
+ def test_accuracy(subject_uri:, expected_by_position:, pending: false)
49
+ dt_start = QaServer::TimeService.current_time
50
+ results = yield if block_given?
51
+ dt_end = QaServer::TimeService.current_time
52
+ if results.blank?
53
+ log(status: UNKNOWN, errmsg: "Search position scenario failed; cause: no results found", expected: expected_by_position,
54
+ target: subject_uri, request_run_time: (dt_end - dt_start), pending: pending)
55
+ return
56
56
  end
57
57
 
58
- def accuracy_scenario?
59
- return false if scenario.expected_by_position.blank? || scenario.subject_uri.blank?
60
- true
61
- end
58
+ check_position(results, subject_uri, expected_by_position, total_run_time: (dt_end - dt_start), pending: pending) # TODO: need to get run times from results
59
+ rescue Exception => e
60
+ dt_end = QaServer::TimeService.current_time
61
+ log(status: FAIL, errmsg: "Exception executing search position scenario; cause: #{e.message}",
62
+ expected: expected_by_position, target: subject_uri, request_run_time: (dt_end - dt_start), pending: pending)
63
+ end
62
64
 
63
- def connection_scenario?
64
- # There are only two types of tests, so if this isn't an accuracy scenario, it must be a connection scenario.
65
- !accuracy_scenario?
66
- end
65
+ def accuracy_scenario?
66
+ return false if scenario.expected_by_position.blank? || scenario.subject_uri.blank?
67
+ true
68
+ end
67
69
 
68
- def check_position(results, subject_uri, expected_by_position, total_run_time)
69
- actual_position = subject_position(results, subject_uri, total_run_time)
70
- return if actual_position.blank?
70
+ def connection_scenario?
71
+ # There are only two types of tests, so if this isn't an accuracy scenario, it must be a connection scenario.
72
+ !accuracy_scenario?
73
+ end
71
74
 
72
- actual_position += 1
73
- if actual_position <= expected_by_position
74
- log(status: PASS, expected: expected_by_position, actual: actual_position, target: subject_uri,
75
- normalization_run_time: total_run_time) # TODO: need to get run times from results
76
- else
77
- log(status: UNKNOWN, errmsg: 'Subject URI not found by the expected position.',
78
- expected: expected_by_position, actual: actual_position, target: subject_uri,
79
- normalization_run_time: total_run_time) # TODO: need to get run times from results
80
- end
75
+ def check_position(results, subject_uri, expected_by_position, total_run_time:, pending:)
76
+ actual_position = subject_position(results, subject_uri, total_run_time, pending)
77
+ return if actual_position.blank?
78
+
79
+ if actual_position <= expected_by_position
80
+ log(status: PASS, expected: expected_by_position, actual: actual_position, target: subject_uri,
81
+ normalization_run_time: total_run_time, pending: pending) # TODO: need to get run times from results
82
+ else
83
+ log(status: UNKNOWN, errmsg: 'Subject URI not found by the expected position.',
84
+ expected: expected_by_position, actual: actual_position, target: subject_uri,
85
+ normalization_run_time: total_run_time, pending: pending) # TODO: need to get run times from results
81
86
  end
87
+ end
82
88
 
83
- def subject_position(results, subject_uri, total_run_time)
84
- 0.upto(results.size - 1) do |position|
85
- return position if results[position][:uri] == subject_uri
86
- end
87
- log(status: UNKNOWN, errmsg: "Search position scenario failed; cause: subject uri (#{subject_uri}) not found in results",
88
- expected: scenario.expected_by_position, target: subject_uri, normalization_run_time: total_run_time) # TODO: need to get run times from results
89
- nil
89
+ def subject_position(results, subject_uri, total_run_time, pending)
90
+ 0.upto(results.size - 1) do |position|
91
+ return position + 1 if results[position][:uri] == subject_uri
90
92
  end
93
+ log(status: UNKNOWN, errmsg: "Search position scenario failed; cause: subject uri (#{subject_uri}) not found in results",
94
+ expected: scenario.expected_by_position, target: subject_uri, normalization_run_time: total_run_time, pending: pending) # TODO: need to get run times from results
95
+ nil
96
+ end
91
97
  end
92
98
  end
@@ -4,14 +4,21 @@ module QaServer
4
4
  class TermScenarioValidator < ScenarioValidator
5
5
  TERM_ACTION = 'term'
6
6
 
7
+ # CONCRETE Implementation: Return value of request_data
8
+ attr_reader :request_data
9
+ private :request_data
10
+
7
11
  # @param scenario [TermScenario] the scenario to run
8
12
  # @param status_log [ScenarioLogger] logger for recording test results
9
13
  # @param validation_type [Symbol] the type of scenarios to run (e.g. VALIDATE_CONNECTION, VALIDATE_ACCURACY, ALL_VALIDATIONS)
10
14
  def initialize(scenario:, status_log:, validation_type: DEFAULT_VALIDATION_TYPE)
11
15
  super
16
+ @request_data = scenario.identifier
12
17
  end
13
18
 
14
- # Run a term scenario and log results.
19
+ private
20
+
21
+ # CONCRETE Implementation: Run a term scenario and log results.
15
22
  def run_connection_scenario
16
23
  test_connection(min_expected_size: scenario.min_result_size, scenario_type_name: 'term') do
17
24
  authority.find(scenario.identifier,
@@ -19,25 +26,23 @@ module QaServer
19
26
  end
20
27
  end
21
28
 
22
- # Run a term scenario and log results.
29
+ # CONCRETE Implementation: Run a term scenario and log results.
23
30
  def run_accuracy_scenario
24
31
  # no accuracy scenarios defined for terms at this time
25
32
  end
26
33
 
27
- private
28
-
29
- def action
30
- TERM_ACTION
31
- end
34
+ def action
35
+ TERM_ACTION
36
+ end
32
37
 
33
- def accuracy_scenario?
34
- # At this time, all scenarios are connection scenarios for terms.
35
- false
36
- end
38
+ def accuracy_scenario?
39
+ # At this time, all scenarios are connection scenarios for terms.
40
+ false
41
+ end
37
42
 
38
- def connection_scenario?
39
- # At this time, all scenarios are connection scenarios for terms.
40
- true
41
- end
43
+ def connection_scenario?
44
+ # At this time, all scenarios are connection scenarios for terms.
45
+ true
46
+ end
42
47
  end
43
48
  end
@@ -1,10 +1,35 @@
1
1
  <script>
2
+ function hide_data() {
3
+ connection_status_section = document.getElementById('connection-status-section');
4
+ if (connection_status_section != null) {
5
+ connection_status_section.style.display = 'none';
6
+ }
7
+ accuracy_status_section = document.getElementById('accuracy-status-section');
8
+ if (accuracy_status_section != null) {
9
+ accuracy_status_section.style.display = 'none';
10
+ }
11
+ comparison_status_section = document.getElementById('comparison-status-section');
12
+ if (comparison_status_section != null) {
13
+ comparison_status_section.style.display = 'none';
14
+ }
15
+ }
16
+
2
17
  function validate_authority(form) {
3
- form.submit();
18
+ show_loading_message();
19
+ hide_data();
20
+ }
21
+
22
+ function show_loading_message() {
4
23
  document.getElementById('status-loading-message').style.display = 'block';
5
- document.getElementById('connection-status-section').style.display = 'none';
6
- document.getElementById('accuracy-status-section').style.display = 'none';
7
- document.getElementById('example-url-warning').style.display = 'none';
24
+ }
25
+ function hide_loading_message() {
26
+ document.getElementById('status-loading-message').style.display = 'none';
27
+ }
28
+ function show_comparison_selector() {
29
+ document.getElementById('comparison-authority-selector').style.display = 'block';
30
+ }
31
+ function hide_comparison_selector() {
32
+ document.getElementById('comparison-authority-selector').style.display = 'none';
8
33
  }
9
34
  </script>
10
35
 
@@ -12,24 +37,43 @@
12
37
 
13
38
  <h2><%= t('qa_server.check_status.title') %></h2>
14
39
 
40
+ <% selected_authority = @presenter.selected_authority %>
41
+ <% selected_comparison = @presenter.selected_comparison %>
15
42
  <%= form_tag({ action: 'index' }, { method: :get }) do %>
16
- <select name="authority" id="authority" class="string multi-value optional form-control form-control multi-text-field" value="" aria-labelledby="authority" onchange="validate_authority(this.form)">
17
- <option value=""><%= t('qa_server.check_status.select_authority') %></option>
18
- <option disabled>──────────</option>
19
- <option value="<%= @presenter.value_all_collections %>"><%= t('qa_server.check_status.show_all') %></option>
20
- <option disabled>──────────</option>
21
- <% @authorities_list.each do |auth_name| %>
22
- <option value="<%= auth_name %>"><%= auth_name.upcase %></option>
23
- <% end %>
24
- </select>
25
- <div class="validation-types">
26
- <%= radio_button_tag(@presenter.value_check_param, @presenter.value_check_connections, :selected) %>
27
- <%= label_tag(@presenter.label_check_connections, t('qa_server.check_status.connections'), class: 'horizontal-list') %>
28
- <%= radio_button_tag(@presenter.value_check_param, @presenter.value_check_accuracy) %>
29
- <%= label_tag(@presenter.label_check_accuracy, t('qa_server.check_status.accuracy'), class: 'horizontal-list') %>
30
- <%= radio_button_tag(@presenter.value_check_param, @presenter.value_all_checks) %>
31
- <%= label_tag(@presenter.label_all_checks, t('qa_server.check_status.all_checks'), class: 'horizontal-list') %>
32
- </div>
43
+ <div id="authority-selector">
44
+ <select name="authority" id="authority" class="string optional form-control form-control" value="" aria-labelledby="authority" onchange="hide_data()">
45
+ <option value=""><%= t('qa_server.check_status.select_authority') %></option>
46
+ <option disabled>──────────</option>
47
+ <option value="<%= @presenter.value_all_collections %>"><%= t('qa_server.check_status.show_all') %></option>
48
+ <option disabled>──────────</option>
49
+ <% @authorities_list.each do |auth_name| %>
50
+ <option value="<%= auth_name %>"<%= " selected" if auth_name == selected_authority %>><%= auth_name.upcase %></option>
51
+ <% end %>
52
+ </select>
53
+ </div>
54
+
55
+ <div id="comparison-authority-selector" style="<%= "display\: block" if @presenter.comparison_status_data? %>">
56
+ Compare with:
57
+ <select name="compare_with" id="compare-with" class="string optional form-control form-control" value="" aria-labelledby="authority" onchange="hide_data()">
58
+ <option value=""><%= t('qa_server.check_status.select_authority') %></option>
59
+ <option disabled>──────────</option>
60
+ <% @authorities_list.each do |auth_name| %>
61
+ <option value="<%= auth_name %>"<%= " selected" if auth_name == selected_comparison %>><%= auth_name.upcase %></option>
62
+ <% end %>
63
+ </select>
64
+ </div>
65
+
66
+ <div class="validation-types">
67
+ <%= radio_button_tag(@presenter.value_check_param, @presenter.value_check_connections, @presenter.connection_tests_checked, onClick: "hide_comparison_selector()") %>
68
+ <%= label_tag(@presenter.label_check_connections, t('qa_server.check_status.connections'), class: 'horizontal-list') %>
69
+ <%= radio_button_tag(@presenter.value_check_param, @presenter.value_check_accuracy, @presenter.accuracy_tests_checked, onClick: "hide_comparison_selector()") %>
70
+ <%= label_tag(@presenter.label_check_accuracy, t('qa_server.check_status.accuracy'), class: 'horizontal-list') %>
71
+ <%= radio_button_tag(@presenter.value_check_param, @presenter.value_check_comparison, @presenter.comparison_tests_checked, onClick: "show_comparison_selector()") %>
72
+ <%= label_tag(@presenter.label_check_comparison, t('qa_server.check_status.comparison'), class: 'horizontal-list') %>
73
+ <%= radio_button_tag(@presenter.value_check_param, @presenter.value_all_checks, false, onClick: "hide_comparison_selector()") %>
74
+ <%= label_tag(@presenter.label_all_checks, t('qa_server.check_status.all_checks'), class: 'horizontal-list') %>
75
+ </div>
76
+ <button type="submit" class="btn btn-primary" id="check-status-go" onclick="validate_authority(this.form)">GO</button>
33
77
  <% end %>
34
78
 
35
79
 
@@ -56,7 +100,7 @@
56
100
  </tr>
57
101
  <% end %>
58
102
  <tr>
59
- <td class="<%= @presenter.status_style_class(status) %>"><%= @presenter.status_label(status) %></td>
103
+ <td class="<%= @presenter.status_style_class(status[:status]) %>"><%= @presenter.status_label(status[:status]) %></td>
60
104
  <td><%= status[:subauthority_name] %></td>
61
105
  <td><%= status[:service] %></td>
62
106
  <td><%= status[:action] %></td>
@@ -75,6 +119,7 @@
75
119
  <tr>
76
120
  <th><%= t('qa_server.check_status.status_table.expected_by_position') %></th>
77
121
  <th><%= t('qa_server.check_status.status_table.actual_position') %></th>
122
+ <th><%= t('qa_server.check_status.status_table.request_data') %></th>
78
123
  <th><%= t('qa_server.check_status.status_table.subject_uri') %></th>
79
124
  <th><%= t('qa_server.check_status.status_table.authority') %></th>
80
125
  <th><%= t('qa_server.check_status.status_table.subauthority') %></th>
@@ -83,10 +128,18 @@
83
128
  <th><%= t('qa_server.check_status.status_table.url') %></th>
84
129
  <th><%= t('qa_server.check_status.status_table.errmsg') %></th>
85
130
  </tr>
131
+ <% current_authority = nil %>
86
132
  <% @presenter.accuracy_status_data.each do |status| %>
133
+ <% unless status[:authority_name] == current_authority %>
134
+ <% current_authority = status[:authority_name] %>
135
+ <tr>
136
+ <td class="table_subheading" colspan="10"><%= current_authority %></td>
137
+ </tr>
138
+ <% end %>
87
139
  <tr>
88
- <td class="position <%= @presenter.status_style_class(status) %>"><%= status[:expected] %></td>
89
- <td class="position <%= @presenter.status_style_class(status) %>"><%= status[:actual] %></td>
140
+ <td class="position <%= @presenter.status_style_class(status[:status]) %>"><%= status[:expected] %></td>
141
+ <td class="position <%= @presenter.status_style_class(status[:status]) %>"><%= status[:actual] %></td>
142
+ <td><%= status[:request_data] %></td>
90
143
  <td><a href="<%= status[:target] %>"><%= status[:target] %></a></td>
91
144
  <td><%= status[:authority_name] %></td>
92
145
  <td><%= status[:subauthority_name] %></td>
@@ -100,4 +153,47 @@
100
153
  </div>
101
154
  <% end %>
102
155
 
156
+ <% if @presenter.comparison_status_data? %>
157
+ <div id="comparison-status-section" class="status-section">
158
+ <h3><%= t('qa_server.check_status.comparison_checks') %></h3>
159
+ <% auth_before = @presenter.comparison_status_data.first[:authority_name][0]%>
160
+ <% auth_after = @presenter.comparison_status_data.first[:authority_name][1]%>
161
+ <table class="status">
162
+ <tr>
163
+ <th class="comparison-header comparison-before bold-left-border" colspan=2><%= auth_before %><br><%= t('qa_server.check_status.status_table.before') %></th>
164
+ <th class="comparison-header comparison-after" colspan=2><%= auth_after %><br><%= t('qa_server.check_status.status_table.after') %></th>
165
+ <th class="comparison-header" colspan=7></th>
166
+ </tr>
167
+ <tr>
168
+ <th class="bold-left-border"><%= t('qa_server.check_status.status_table.expected_by_position') %></th>
169
+ <th><%= t('qa_server.check_status.status_table.actual_position') %></th>
170
+ <th class="bold-left-border"><%= t('qa_server.check_status.status_table.expected_by_position') %></th>
171
+ <th><%= t('qa_server.check_status.status_table.actual_position') %></th>
172
+ <th class="bold-left-border"><%= t('qa_server.check_status.status_table.request_data') %></th>
173
+ <th><%= t('qa_server.check_status.status_table.subject_uri') %></th>
174
+ <th><%= t('qa_server.check_status.status_table.subauthority') %></th>
175
+ <th><%= t('qa_server.check_status.status_table.service') %></th>
176
+ <th><%= t('qa_server.check_status.status_table.action') %></th>
177
+ <th><%= t('qa_server.check_status.status_table.url') %></th>
178
+ <th><%= t('qa_server.check_status.status_table.errmsg') %></th>
179
+ </tr>
180
+ <% @presenter.comparison_status_data.each do |status| %>
181
+ <tr>
182
+ <td class="position bold-left-border <%= @presenter.status_style_class(status[:status][0]) %>"><%= status[:expected][0] %></td>
183
+ <td class="position <%= @presenter.status_style_class(status[:status][0]) %>"><%= status[:actual][0] %></td>
184
+ <td class="position bold-left-border <%= @presenter.status_style_class(status[:status][1]) %>"><%= status[:expected][1] %></td>
185
+ <td class="position <%= @presenter.status_style_class(status[:status][1]) %>"><%= status[:actual][1] %></td>
186
+ <td class="bold-left-border"><%= status[:request_data] %></td>
187
+ <td><a href="<%= status[:target] %>"><%= status[:target] %></a></td>
188
+ <td><%= status[:subauthority_name] %></td>
189
+ <td><%= status[:service] %></td>
190
+ <td><%= status[:action] %></td>
191
+ <td><a href="<%= status[:url][0] %>"><%= status[:url][0] %></a>, <a href="<%= status[:url][1] %>"><%= status[:url][1] %></a></td>
192
+ <td><%= status[:err_message] %></td>
193
+ </tr>
194
+ <% end %>
195
+ </table>
196
+ </div>
197
+ <% end %>
198
+
103
199
  </div>