Skip to content

Commit

Permalink
a11y: spec testing/refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
cycomachead committed Sep 25, 2024
1 parent 6817a8c commit a7b4d37
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 69 deletions.
32 changes: 9 additions & 23 deletions utilities/specs/accessibility_spec.rb
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
72 changes: 72 additions & 0 deletions utilities/specs/bjc_helper.rb
Original file line number Diff line number Diff line change
@@ -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
49 changes: 3 additions & 46 deletions utilities/specs/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,59 +20,16 @@
require 'rack'

require 'capybara/rspec'
# require 'capybara-screenshot/rspec'
require 'rack/test'
require 'axe-rspec'
require 'axe-capybara'
require 'capybara/dsl'
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
Expand Down Expand Up @@ -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

Expand Down

0 comments on commit a7b4d37

Please sign in to comment.