Skip to content

Commit

Permalink
Merge pull request #43 from berkeley-cdss/specs-cleanup
Browse files Browse the repository at this point in the history
Tidy a11y specs
  • Loading branch information
cycomachead authored Aug 15, 2024
2 parents d793476 + d239703 commit 64d2d07
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 117 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/rspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ jobs:
with:
# The Ruby version is determined by either a `.ruby-version` or a `.tool-versions` file in root of the repo.
bundler-cache: true
- name: Run rspec tests
- name: Run a11y tests
run: |
bundle exec rspec
- name: summary
if: always()
if: failure()
run: ruby spec/support/spec_summary.rb
- name: Keep screenshots from failed tests
uses: actions/upload-artifact@v4
Expand Down
7 changes: 3 additions & 4 deletions _includes/footer_custom.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<!-- This file comes from Just The Docs.
This footer should be included on all EECS/DS sites.
-->

Expand All @@ -8,8 +7,8 @@
{%- endif -%}

<p class="text-small text-grey-dk-100 my-1">
<a rel="nofollow noopener" href="https://dap.berkeley.edu/get-help/report-web-accessibility-issue" target="_blank" class="pr-2">Accessibility <i class="fa-solid fa-external-link" aria-hidden=true></i></a>
<a rel="nofollow noopener" href="https://ophd.berkeley.edu/policies-and-procedures/nondiscrimination-policy-statement" target="_blank" class="px-2">Nondiscrimination <i class="fa-solid fa-external-link" aria-hidden=true></i></a>
<a rel="nofollow noopener" href="https://dap.berkeley.edu/get-help/report-web-accessibility-issue" target="_blank" class="pr-2">Accessibility</a>
<a rel="nofollow noopener" href="https://ophd.berkeley.edu/policies-and-procedures/nondiscrimination-policy-statement" target="_blank" class="px-2">Nondiscrimination</a>
</p>

<!-- Use this to add additional content. -->
Expand All @@ -18,5 +17,5 @@
</p>

<p class="fs-1 text-lighter my-1">
This site is built following the <a href="https://github.com/just-the-docs/just-the-docs" target="_bank" rel="noopener">Berkeley Class Site <i class="fa-solid fa-external-link" aria-hidden=true></i></a> template, which is generously based on the <a href="https://github.com/kevinl/just-the-class" target="_bank" rel="noopener">Just the Class <i class="fa-solid fa-external-link" aria-hidden=true></i></a>, and <a href="https://github.com/just-the-docs/just-the-docs" target="_bank" rel="noopener">Just the Docs <i class="fa-solid fa-external-link" aria-hidden=true></i></a> templates.
This site is built following the <a href="https://github.com/just-the-docs/just-the-docs" target="_blank" rel="noopener">Berkeley Class Site</a> template, which is generously based on the <a href="https://github.com/kevinl/just-the-class" target="_blank" rel="noopener">Just the Class</a>, and <a href="https://github.com/just-the-docs/just-the-docs" target="_blank" rel="noopener">Just the Docs</a> templates.
</p>
19 changes: 0 additions & 19 deletions _includes/head_custom.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,3 @@
<link href="{{ site.baseurl }}/assets/vendor/fontawesome/css/fontawesome.css" rel="stylesheet" />
<link href="{{ site.baseurl }}/assets/vendor/fontawesome/css/solid.css" rel="stylesheet" />
<!-- <link href="{{ site.baseurl }}/assets/vendor/fontawesome/css/brands.css" rel="stylesheet" /> -->

<script>
document.addEventListener("DOMContentLoaded", function() {
if (jtd && localStorage['jtd-theme']) {
jtd.setTheme(localStorage['jtd-theme']);
}

const toggleDarkMode = document.querySelector('.js-toggle-dark-mode');
jtd.addEvent(toggleDarkMode, 'click', function() {
if (jtd.getTheme() === 'dark') {
localStorage['jtd-theme'] = 'light';
jtd.setTheme('light');
} else {
jtd.setTheme('dark');
localStorage['jtd-theme'] = 'dark';
}
});
});
</script>
10 changes: 8 additions & 2 deletions _includes/nav_footer_custom.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
<!-- This file adds links at the bottom of the sidebar on the left. -->

{% if site.class_archive_path %}
<section class="site-footer" aria-label="Footer: site archive">
<section class="site-footer py-1" aria-label="Footer: site archive">
<a href="{{ site.class_archive_path }}"
target="_blank" rel="noopener nofollow">View all course offerings
<i class="fa-solid fa-external-link" aria-hidden="true"></i></a>
</a>
</section>
{% endif %}

{% if site.hide_color_scheme_toggle != 'true' %}
<div class="site-footer m-1">
{% include toggle-color-scheme.html %}
</div>
{% endif %}
80 changes: 80 additions & 0 deletions _includes/toggle-color-scheme.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{% capture btn_aria_label %}
{%- if site.color_scheme == 'dark' -%}
Switch to Light Mode
{%- else -%}
Switch to Dark Mode
{%- endif -%}
{% endcapture %}

<span class="fs-3">
<button type="button"
class="btn js-toggle-dark-mode btn-outline"
style="margin-right: -3px; border-top-right-radius: 0; border-bottom-right-radius: 0;"
aria-label="{{ btn_aria_label }}">
{%- if site.color_scheme == 'dark' -%}
🔆 Light Mode
{%- else -%}
🌙 Dark Mode
{%- endif -%}
</button>
<button type="button"
class="btn js-unset-color-scheme btn-outline px-2"
style="margin-left: -3px; border-top-left-radius: 0; border-bottom-left-radius: 0;"
aria-label="Reset color scheme"
></button>
</span>

<script>
document.addEventListener("DOMContentLoaded", function() {
if (!jtd) { return; }

const toggleSchemeBtn = document.querySelector('.js-toggle-dark-mode');
const unsetColorScheme = document.querySelector('.js-unset-color-scheme');

// If the browser suggests a color scheme, and user hasn't saved/switch one yet..
if (window.matchMedia && !localStorage['jtd-theme']) {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
jtd.setTheme('dark');
toggleSchemeBtn.textContent = '🔆 Light Mode';
toggleSchemeBtn.ariaLabel = 'Switch to Light Mode';
} else if (window.matchMedia('(prefers-color-scheme: light)').matches) {
jtd.setTheme('light');
toggleSchemeBtn.textContent = '🌙 Dark Mode';
toggleSchemeBtn.ariaLabel = 'Switch to Dark Mode';
}
} else if (localStorage['jtd-theme']) {
jtd.setTheme(localStorage['jtd-theme']);
}

jtd.addEvent(toggleSchemeBtn, 'click', function() {
if (jtd.getTheme() === 'dark') {
localStorage['jtd-theme'] = 'light';
jtd.setTheme('light');
toggleSchemeBtn.textContent = '🌙 Dark Mode';
toggleSchemeBtn.ariaLabel = 'Switch to Dark Mode';
} else {
jtd.setTheme('dark');
localStorage['jtd-theme'] = 'dark';
toggleSchemeBtn.textContent = '🔆 Light Mode';
toggleSchemeBtn.ariaLabel = 'Switch to Light Mode';
}
});

// Add a way to unset the saved theme.
// "default" respect's the site config setting, but not the user browser pref
// So, check the pref and set the theme to the preferred one, if possible.
jtd.addEvent(unsetColorScheme, 'click', function() {
delete localStorage['jtd-theme'];

if (window.matchMedia) {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
jtd.setTheme('dark');
} else if (window.matchMedia('(prefers-color-scheme: light)').matches) {
jtd.setTheme('light');
}
} else {
jtd.setTheme('default');
}
});
});
</script>
7 changes: 7 additions & 0 deletions _sass/berkeley/berkeley.scss
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,10 @@ summary {
.text-lighter {
color: $body-lighter-color;
}

a[target="_blank"]::after {
font-family: 'Font Awesome 6 Free';
font-weight: 900;
content: "\f08e";
padding: 0 0.25rem;
}
5 changes: 0 additions & 5 deletions home.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ seo:

# UC Berkeley Class Site Template

<p>
<button class="btn js-toggle-dark-mode">Swap color scheme</button>
</p>


Just the Class is a GitHub Pages template developed for the purpose of quickly deploying course websites. In addition to serving plain web pages and files, it provides a boilerplate for:

- [announcements](announcements.md),
Expand Down
29 changes: 18 additions & 11 deletions spec/accessibility_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,44 @@
# spec_helper ensures the webiste is built and can be served locally
require 'spec_helper'

ALL_PAGES = load_site_urls
puts "Running tests on #{ALL_PAGES.count} pages."
puts " - #{ALL_PAGES.join("\n - ")}\n#{'=' * 72}\n\n"

# Axe-core test standards groups
# See https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#axe-core-tags
required_a11y_standards = %i[wcag2a wcag2aa]
complete_a11y_standards = %i[wcag21a wcag21 wcag22aa best-practice secion508]
# Tests are segmented in 2.0, 2.1 and 2.2+
# In most places WCAG 2.1AA is the minimum requirement, but 2.2 is the current WCAG Standard.
required_a11y_standards = %i[wcag2a wcag2aa wcag21a wcag21aa]
complete_a11y_standards = %i[wcag22aa best-practice secion508]

# axe-core rules that are not required to be accessible / do not apply
# You may temporarily want to add rules here during development.
# See: https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md
skipped_rules = []
# These are elements that are not required to be accessible
# It should be rare to add to this list. This disables all rules for an element.
# e.g. <img data-a11y-errors="true" src="..." /> would pass even though it's missing alt text.
excluded_elements = [
'[data-a11y-external-errors="true"]'
'[data-a11y-errors="true"]'
]

# We must call this to ensure the build it up-to-date.
build_jekyll_site!
ALL_PAGES = load_sitemap
puts "Running tests on #{ALL_PAGES.count} pages."
puts " - #{ALL_PAGES.join("\n - ")}\n\n"

ALL_PAGES.each do |path|
describe 'page is accessible', :js, type: :feature do
describe "#{path} is accessible", :js, type: :feature do
before do
visit(path)
end

it "#{path} meets WCAG 2.0" do
it 'meets WCAG 2.1' do
expect(page).to be_axe_clean
.according_to(*required_a11y_standards, "#{path} does NOT meet WCAG 2.0 AA")
.according_to(*required_a11y_standards)
.skipping(*skipped_rules)
.excluding(*excluded_elements)
end

it "#{path} meets WCAG 2.2" do
it 'meets WCAG 2.2' do
expect(page).to be_axe_clean
.according_to(*complete_a11y_standards)
.skipping(*skipped_rules)
Expand Down
78 changes: 7 additions & 71 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#
# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration

require 'jekyll'
require 'rspec'
require 'rack'
require 'yaml'
Expand All @@ -31,80 +30,18 @@
require 'axe-rspec'
require 'axe-capybara'

# ------------
# Tools to build / compile the Jekyll site and extract the sitemap
def site_config
# TODO(template): We should standardize the build for specs
# Consider simplifying baseurl
# Consider forcing the desination folder
# Override the local URL too? Would it break the sitemap?
# Note: Config keys must be strings and thus use => style hashes.
@site_config ||= Jekyll.configuration({
'sass' => { 'quiet_deps' => true }
})
end

@site = Jekyll::Site.new(site_config)
@site.process
puts 'Site build complete'

def load_site_urls
puts 'Running accessibility tests'
sitemap_text = File.read('_site/sitemap.xml')
sitemap_links = sitemap_text.scan(%r{<loc>.+</loc>})
sitemap_links.filter_map do |link|
link = link.gsub("<loc>#{site_config['url']}", '').gsub('</loc>', '')
# Skip non-html pages
# (FUTURE?) Are there other pages that should be audited for accessibility?
# (e.g. PDFs, documents. They'd need a different checker.)
next unless link.end_with?('.html') || link.end_with?('/')

link
end.sort
end
# --------
require_relative 'support/jekyll'

# This is the root of the repository, e.g. the bjc-r directory
# Update this is you move this file.
# Used to set the path for a local webserver.
# Update this if you move this file.
REPO_ROOT = File.expand_path('../', __dir__)

# https://nts.strzibny.name/how-to-test-static-sites-with-rspec-capybara-and-webkit/
class StaticSite
attr_reader :root, :server

# TODO: Rack::File will be deprecated soon. Find a better solution.
def initialize(root)
@root = root
@server = Rack::Files.new(root)
end

def call(env)
# Remove the /baseurl prefix, which is present in all URLs, but not in the file system.
path = "_site#{env['PATH_INFO'].gsub(site_config['baseurl'], '/')}"

env['PATH_INFO'] = if path.end_with?('/') && exists?("#{path}index.html")
"#{path}index.html"
elsif !exists?(path) && exists?("#{path}.html")
"#{path}.html"
else
path
end

server.call(env)
end

def exists?(path)
File.exist?(File.join(root, path))
end
end
# ---------

Capybara.register_driver :chrome_headless do |app|
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
# macbook air ~13" screen size, with an absurd height for full size screenshots.
# MacBook Air ~13" screen size, with an absurd height to capture more content.
options.add_argument('--window-size=1280,4000')

Capybara::Selenium::Driver.new(app, browser: :chrome, options:)
Expand All @@ -120,7 +57,9 @@ def exists?(path)
end

Capybara::Screenshot.register_filename_prefix_formatter(:rspec) do |example|
"tmp/capybara/screenshot_#{example.description.gsub('/', '-').gsub(' ', '-').gsub(%r{^.*/spec/}, '')}"
page = example.example_group.top_level_description.gsub(%r{^/}, '').gsub('/', '-').gsub(' is accessible', '')
standards = example.description.split.last
"tmp/capybara/screenshot_#{page}_#{standards}"
end

Capybara::Screenshot.autosave_on_failure = true
Expand All @@ -132,11 +71,8 @@ def exists?(path)
Capybara.app = Rack::Builder.new do
use Rack::Lint
run StaticSite.new(REPO_ROOT)
# map '/' do
# end
end.to_app

# ---------
RSpec.configure do |config|
# Allow rspec to use `--only-failures` and `--next-failure` flags
# Ensure that `tmp` is in your `.gitignore` file
Expand Down
Loading

0 comments on commit 64d2d07

Please sign in to comment.