diff --git a/utilities/specs/accessibility_spec.rb b/utilities/specs/accessibility_spec.rb index 4995c5618..ed096b606 100644 --- a/utilities/specs/accessibility_spec.rb +++ b/utilities/specs/accessibility_spec.rb @@ -1,19 +1,15 @@ # frozen_string_literal: true -# Run accessibility specs for all pages in the webiste. +# Run accessibility specs for all pages in the website. # This runs the axe accessibility checker on each page in a headless browser. -require 'nokogiri' - -# Load our custom BJC tools -require_relative '../build-tools/bjc_helpers' -require_relative '../build-tools/course' -require_relative '../build-tools/topic' - -# spec_helper ensures the webiste is built and can be served locally +# spec_helper ensures the website is built and can be served locally +require_relative './bjc_helper' require_relative './spec_helper' -# ===== Page / Couse List +include BJCSpecs + +# ===== Page / Course List # Use course as a tag (`rspec --tag bjc4nyc`) to run only the tests for that course. COURSES = %w[ bjc4nyc @@ -22,18 +18,7 @@ bjc4nyc_teacher sparks-teacher ] -ALL_PAGES = load_site_urls(COURSES) -# A handful of pages we should ensure are compliant. -ALL_PAGES['general'] = [ - '/bjc-r/', - '/bjc-r/docs/style_guide.html', - '/bjc-r/docs/best_practices.html', - '/bjc-r/docs/translations.html', - '/bjc-r/topic/topic.html', - '/bjc-r/topic/topic.es.html', - '/bjc-r/sparks/design-principles.html', - '/bjc-r/mini/index.html' -] +ALL_PAGES = BJCSpecs.complete_bjc_grouped_file_list(COURSES) # =============================== def test_tags(tags) @@ -66,7 +51,7 @@ def a11y_test_cases(course, url) # See https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#axe-core-tags required_a11y_standards = %i[wcag2a wcag2aa] # These are currently skipped until the basic tests are passing. - complete_a11y_standards = %i[wcag21a wcag21aa wcag22aa wcag2a-obsolete best-practice secion508] + complete_a11y_standards = %i[wcag21a wcag21aa wcag22aa wcag2a-obsolete best-practice section508] # axe-core rules that are not required to be accessible / do not apply # See: https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md @@ -92,6 +77,7 @@ def a11y_test_cases(course, url) before(:each) do visit(url) + # binding.irb if page.html.match?(/File not found:/) skip("TODO: #{url} is a 404 page.") end diff --git a/utilities/specs/bjc_helper.rb b/utilities/specs/bjc_helper.rb new file mode 100644 index 000000000..20cf1e76e --- /dev/null +++ b/utilities/specs/bjc_helper.rb @@ -0,0 +1,72 @@ + +require 'nokogiri' + +# Load our custom BJC tools +require_relative '../build-tools/bjc_helpers' +require_relative '../build-tools/course' +require_relative '../build-tools/topic' + +module BJCSpecs + # The list of all courses in BJC + COURSES = %w[ + bjc4nyc + bjc4nyc.es + sparks + bjc4nyc_teacher + sparks-teacher + ] + + # This is a map of all courses/groups + ALL_PAGES = {} + ALL_PAGES['general'] = [ + '/bjc-r/', + '/bjc-r/docs/style_guide.html', + '/bjc-r/docs/best_practices.html', + '/bjc-r/docs/translations.html', + '/bjc-r/topic/topic.html', + '/bjc-r/topic/topic.es.html', + '/bjc-r/sparks/design-principles.html', + '/bjc-r/mini/index.html' + ] + + def load_site_urls(courses) + # Map is a course_name => [url1, url2, ...] + courses.map do |course| + puts "Building URLs for #{course}..." + [course, load_all_urls_in_course("#{course}.html")] + end.to_h + end + + def extract_urls_from_page(topic_file, course) + topic_file = File.join(File.dirname(__FILE__), '..', '..', 'topic', topic_file) + lang = topic_file.match(/\.(\w\w)\.topic/) ? Regexp.last_match(1) : 'en' + topic_parser = BJCTopic.new(topic_file, course: course, language: lang) + topic_parser.augmented_page_paths_in_topic + end + + def load_all_urls_in_course(course) + # Read the course page, then add all "Unit" URLs to the list + # TODO: Use the BJCCourse class to extract the URLs + results = [ "/bjc-r/course/#{course}" ] + course_file = File.join(File.dirname(__FILE__), '..', '..', 'course', course) + doc = Nokogiri::HTML(File.read(course_file)) + urls = doc.css('.topic_container .topic_link a').map { |url| url['href'] } + + topic_pages = urls.filter_map do |url| + next unless url.match?(/\.topic/) + + query_separator = url.match?(/\?/) ? '&' : '?' + results << "#{url}#{query_separator}course=#{course}" + topic_file = url.match(/topic=(.*\.topic)/)[1] + extract_urls_from_page(topic_file, course) + end.flatten + + results << topic_pages + results << urls.filter_map { |url| "#{url}#{url.match?(/\?/) ? '&' : '?'}course=#{course}" if !url.match?(/\.topic/) } + results.flatten.reject { |u| !u.start_with?('/bjc-r') }.uniq + end + + def complete_bjc_grouped_file_list(courses) + ALL_PAGES.merge(load_site_urls(courses)) + end +end diff --git a/utilities/specs/spec_helper.rb b/utilities/specs/spec_helper.rb index 5d529e004..d13fb98ab 100644 --- a/utilities/specs/spec_helper.rb +++ b/utilities/specs/spec_helper.rb @@ -20,7 +20,6 @@ require 'rack' require 'capybara/rspec' -# require 'capybara-screenshot/rspec' require 'rack/test' require 'axe-rspec' require 'axe-capybara' @@ -28,51 +27,9 @@ require 'capybara/session' require 'capybara-screenshot' -# ===== bjc-r specific config/parsing.... -# TODO: This code should be moved to support/parsing sections. -def load_site_urls(courses) - # Map is a course_name => [url1, url2, ...] - courses.map do |course| - puts "Buidling URLs for #{course}..." - [course, load_all_urls_in_course("#{course}.html")] - end.to_h -end - -def extract_urls_from_page(topic_file, course) - topic_file = File.join(File.dirname(__FILE__), '..', '..', 'topic', topic_file) - lang = topic_file.match(/\.(\w\w)\.topic/) ? Regexp.last_match(1) : 'en' - topic_parser = BJCTopic.new(topic_file, course: course, language: lang) - topic_parser.augmented_page_paths_in_topic -end - -def load_all_urls_in_course(course) - # Read the course page, then add all "Unit" URLs to the list - # TODO: Use the BJCCourse class to extract the URLs - results = [ "/bjc-r/course/#{course}" ] - course_file = File.join(File.dirname(__FILE__), '..', '..', 'course', course) - doc = Nokogiri::HTML(File.read(course_file)) - urls = doc.css('.topic_container .topic_link a').map { |url| url['href'] } - - topic_pages = urls.filter_map do |url| - next unless url.match?(/\.topic/) - - query_separator = url.match?(/\?/) ? '&' : '?' - results << "#{url}#{query_separator}course=#{course}" - topic_file = url.match(/topic=(.*\.topic)/)[1] - extract_urls_from_page(topic_file, course) - end.flatten - - results << topic_pages - results << urls.filter_map { |url| "#{url}#{url.match?(/\?/) ? '&' : '?'}course=#{course}" if !url.match?(/\.topic/) } - results.flatten.reject { |u| !u.start_with?('/bjc-r') }.uniq -end - -# ======== end bjc-r stuff ========== - # Used to set the path for a local webserver. -# Update this if you move this file. -DESTINATION = 'tmp/specs/' -FILE_SERVER_ROOT = File.expand_path("../", __dir__) +# For simplicity, this is one level above bjc-r/ so the prefix is easily handled. +FILE_SERVER_ROOT = File.expand_path("../../../", __dir__) Capybara.register_driver :chrome_headless do |app| options = Selenium::WebDriver::Chrome::Options.new @@ -114,7 +71,7 @@ def load_all_urls_in_course(course) Capybara.server = :webrick Capybara.app = Rack::Builder.new do use Rack::Lint - use Rack::Static, { urls: ['/'], root: FILE_SERVER_ROOT, index: 'index.html' } + use Rack::Static, { urls: [''], root: "#{FILE_SERVER_ROOT}/", index: 'index.html' } run Rack::Files.new(FILE_SERVER_ROOT) end.to_app