diff --git a/app/services/epub_accessibility_metadata_indexing_service.rb b/app/services/epub_accessibility_metadata_indexing_service.rb index 13964b8c0..2695ed289 100644 --- a/app/services/epub_accessibility_metadata_indexing_service.rb +++ b/app/services/epub_accessibility_metadata_indexing_service.rb @@ -70,7 +70,7 @@ def accessibility_features values&.map { |value| value&.text&.strip } end # want to ensure the indexer is set to nil not [] if these are not present, keeping the field off the doc entirely - values.presence + values.presence&.sort end def access_mode @@ -83,21 +83,40 @@ def access_mode values&.map { |value| value&.text&.strip } end # want to ensure the indexer is set to nil not [] if these are not present, keeping the field off the doc entirely - values.presence + values.presence&.sort end def access_mode_sufficient - # this one has multiple entries in one value, comma separated - values = @content_metadata.at_css("meta[#{@meta_attribute}='schema:accessModeSufficient']") - return nil if values.blank? - values = @epub_2 ? values['content']&.split(',') : values.text&.split(',') - values&.reject(&:blank?)&.map(&:strip) + # this one has multiple entries in separate meta tags, each of which can have one or more comma-separated values in it + values = @content_metadata.css("meta[#{@meta_attribute}='schema:accessModeSufficient']") + + values = if @epub_2 + values&.map { |value| value['content']&.strip } + else + values&.map { |value| value&.text&.strip } + end + # want to ensure the indexer is set to nil not [] if these are not present, keeping the field off the doc entirely + values.presence&.sort end def conforms_to + # need to check for both the EPUB Accessibility 1.1 style and the older 1.0 style, see: + # https://kb.daisy.org/publishing/docs/metadata/evaluation.html#a11y-transition + + # check for 1.1 first value = @content_metadata.at_css("meta[#{@meta_attribute}='dcterms:conformsTo']") + + value = if value.present? + @epub_2 ? value['content']&.strip : value.text&.strip + end + return value if value.present? + + # look for EPUB Accessibility 1.0 style instead + value = @content_metadata.at_css("link[rel='dcterms:conformsTo']") + value = value['href']&.strip if value.present? + return nil if value.blank? - @epub_2 ? value['content']&.strip : value.text&.strip + value end def certified_by @@ -114,10 +133,10 @@ def certifier_credential def screen_reader_friendly if @access_mode_sufficient.present? - if @access_mode_sufficient.count == 1 && @access_mode_sufficient[0] == 'textual' - 'true' + if @access_mode_sufficient.any? { |value| value == 'textual' } + 'yes' else - 'false' + 'no' end else # I guess it's OK that this will always have a value even if all the other a11y metadata is missing. diff --git a/spec/services/epub_accessibility_metadata_indexing_service_spec.rb b/spec/services/epub_accessibility_metadata_indexing_service_spec.rb index 85151ae58..f904dd034 100644 --- a/spec/services/epub_accessibility_metadata_indexing_service_spec.rb +++ b/spec/services/epub_accessibility_metadata_indexing_service_spec.rb @@ -157,126 +157,335 @@ let(:all_a11y_metadata_doc_sans_epub_version) { { "epub_a11y_access_mode_ssim" => ["textual", "visual"], "epub_a11y_access_mode_sufficient_ssim" => ["textual", - "visual"], - "epub_a11y_accessibility_features_ssim" => ["tableOfContents", - "readingOrder", - "ARIA", + "textual,visual", + "textual,visual"], + "epub_a11y_accessibility_features_ssim" => ["ARIA", + "alternativeText", + "displayTransformability", + "index", "pageBreakMarkers", "pageNavigation", - "alternativeText", "printPageNumbers", - "index", + "readingOrder", "structuralNavigation", - "displayTransformability"], + "tableOfContents"], "epub_a11y_accessibility_summary_ssi" => "A very complex book with 15 images, 10 tables, and complex formatting...", "epub_a11y_certified_by_ssi" => "A11yCo", "epub_a11y_certifier_credential_ssi" => "https://a11yfoo.org/certification", "epub_a11y_conforms_to_ssi" => "EPUB Accessibility 1.1 - WCAG 2.1 Level AA", - "epub_a11y_screen_reader_friendly_ssi" => "false" } } - - context 'EPUB 3.0 content file with no a11y metadata present' do - let(:epub_content_file) do - <<~XML - - - I am here to act as a non-a11y entry. - - - XML + "epub_a11y_screen_reader_friendly_ssi" => "yes" } } + + context 'EPUB 3.0 content file' do + context 'no a11y metadata present' do + let(:epub_content_file) do + <<~XML + + + I am here to act as a non-a11y entry. + + + XML + end + + it 'only indexes epub_version_ssi and the derived epub_a11y_screen_reader_friendly_ssi field' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc).to eq(missing_a11y_metadata_doc_sans_epub_version.merge({ "epub_version_ssi" => "3.0" })) + end end - it 'only indexes epub_version_ssi and the derived epub_a11y_screen_reader_friendly_ssi field' do - described_class.index(epub.id, epub_solr_doc) - expect(epub_solr_doc).to eq(missing_a11y_metadata_doc_sans_epub_version.merge({ "epub_version_ssi" => "3.0" })) + context 'all a11y metadata present' do + let(:epub_content_file) do + <<~XML + + + I am here to act as a non-a11y entry. + textual + visual + + textual,visual + textual + tableOfContents + readingOrder + ARIA + pageBreakMarkers + pageNavigation + alternativeText + printPageNumbers + index + structuralNavigation + displayTransformability + none + A very complex book with 15 images, 10 tables, and complex formatting... + EPUB Accessibility 1.1 - WCAG 2.1 Level AA + A11yCo + https://a11yfoo.org/certification + + textual,visual + + + XML + end + + it 'indexes all expected fields' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc).to eq(all_a11y_metadata_doc_sans_epub_version.merge({ "epub_version_ssi" => "3.0" })) + end end - end - context 'EPUB 3.0 content file with all a11y metadata present' do - let(:epub_content_file) do - <<~XML - - - I am here to act as a non-a11y entry. - textual - visual - textual,visual - tableOfContents - readingOrder - ARIA - pageBreakMarkers - pageNavigation - alternativeText - printPageNumbers - index - structuralNavigation - displayTransformability - none - A very complex book with 15 images, 10 tables, and complex formatting... - EPUB Accessibility 1.1 - WCAG 2.1 Level AA - A11yCo - https://a11yfoo.org/certification - textual,visual - - - XML + describe 'dcterms:conformsTo' do + context 'EPUB Accessibility 1.0 specification' do + let(:epub_content_file) do + <<~XML + + + I am here to act as a non-a11y entry. + + + + XML + end + + it 'indexes the value into "epub_a11y_conforms_to_ssi"' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc['epub_a11y_conforms_to_ssi']).to eq('http://www.idpf.org/epub/a11y/accessibility-20170105.html#wcag-aa') + end + end + + context 'EPUB Accessibility 1.1 specification' do + let(:epub_content_file) do + <<~XML + + + I am here to act as a non-a11y entry. + EPUB Accessibility 1.1 - WCAG 2.0 Level AA + + + XML + end + + it 'indexes the value into "epub_a11y_conforms_to_ssi"' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc['epub_a11y_conforms_to_ssi']).to eq('EPUB Accessibility 1.1 - WCAG 2.0 Level AA') + end + end end - it 'indexes all expected fields' do - described_class.index(epub.id, epub_solr_doc) - expect(epub_solr_doc).to eq(all_a11y_metadata_doc_sans_epub_version.merge({ "epub_version_ssi" => "3.0" })) + describe 'screen reader friendly' do + context 'no accessibility metadata present (i.e. no accessModeSufficient field to work from)' do + let(:epub_content_file) do + <<~XML + + + I am here to act as a non-a11y entry. + + + XML + end + + it 'indexes "unknown"' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc['epub_a11y_screen_reader_friendly_ssi']).to eq('unknown') + end + end + + context 'accessModeSufficient is present but no value of "textual" by itself exists' do + let(:epub_content_file) do + <<~XML + + + I am here to act as a non-a11y entry. + + textual,visual + visual + textual,visual + + + XML + end + + it 'indexes "false"' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc['epub_a11y_screen_reader_friendly_ssi']).to eq('no') + end + end + + context 'accessModeSufficient is present, and a value of "textual" by itself does exist' do + let(:epub_content_file) do + <<~XML + + + I am here to act as a non-a11y entry. + + textual,visual + textual + textual,visual + + + XML + end + + it 'indexes "false"' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc['epub_a11y_screen_reader_friendly_ssi']).to eq('yes') + end + end end end - context 'EPUB 2.0 content file with no a11y metadata present' do - let(:epub_content_file) do - <<~XML - - - - - - XML + context 'EPUB 2.0 content file' do + context 'no a11y metadata present' do + let(:epub_content_file) do + <<~XML + + + + + + XML + end + + it 'only indexes epub_version_ssi and the derived epub_a11y_screen_reader_friendly_ssi field' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc).to eq(missing_a11y_metadata_doc_sans_epub_version.merge({ "epub_version_ssi" => "2.0" })) + end end - it 'only indexes epub_version_ssi and the derived epub_a11y_screen_reader_friendly_ssi field' do - described_class.index(epub.id, epub_solr_doc) - expect(epub_solr_doc).to eq(missing_a11y_metadata_doc_sans_epub_version.merge({ "epub_version_ssi" => "2.0" })) + context 'all a11y metadata present' do + let(:epub_content_file) do + <<~XML + + + + + + + + + + + + + + + + + + " + + + + + + + + + + XML + end + + it 'indexes all expected fields' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc).to eq(all_a11y_metadata_doc_sans_epub_version.merge({ "epub_version_ssi" => "2.0" })) + end end - end - context 'EPUB 2.0 content file with all a11y metadata present' do - let(:epub_content_file) do - <<~XML - - - - - - - - - - - - - - - - " - - - - - - - - - XML + describe 'dcterms:conformsTo' do + context 'EPUB Accessibility 1.0 specification' do + let(:epub_content_file) do + <<~XML + + + + + + + XML + end + + it 'indexes the value into "epub_a11y_conforms_to_ssi"' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc['epub_a11y_conforms_to_ssi']).to eq('http://www.idpf.org/epub/a11y/accessibility-20170105.html#wcag-aa') + end + end + + context 'EPUB Accessibility 1.1 specification' do + let(:epub_content_file) do + <<~XML + + + + + + + XML + end + + it 'indexes the value into "epub_a11y_conforms_to_ssi"' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc['epub_a11y_conforms_to_ssi']).to eq('EPUB Accessibility 1.1 - WCAG 2.0 Level AA') + end + end end - it 'indexes all expected fields' do - described_class.index(epub.id, epub_solr_doc) - expect(epub_solr_doc).to eq(all_a11y_metadata_doc_sans_epub_version.merge({ "epub_version_ssi" => "2.0" })) + describe 'screen reader friendly' do + context 'no accessibility metadata present (i.e. no accessModeSufficient field to work from)' do + let(:epub_content_file) do + <<~XML + + + + + + XML + end + + it 'indexes "unknown"' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc['epub_a11y_screen_reader_friendly_ssi']).to eq('unknown') + end + end + + context 'accessModeSufficient is present but no value of "textual" by itself exists' do + let(:epub_content_file) do + <<~XML + + + + + + + + + + XML + end + + it 'indexes "false"' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc['epub_a11y_screen_reader_friendly_ssi']).to eq('no') + end + end + + context 'accessModeSufficient is present, and a value of "textual" by itself does exist' do + let(:epub_content_file) do + <<~XML + + + + + + + + + + XML + end + + it 'indexes "false"' do + described_class.index(epub.id, epub_solr_doc) + expect(epub_solr_doc['epub_a11y_screen_reader_friendly_ssi']).to eq('yes') + end + end end end end