From 753ff022ad2f4c9ca3d731ddfa26b14d535bebd9 Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 11:58:42 -0700 Subject: [PATCH 01/16] Update bundle to includes specs/accessibility tools --- .github/workflows/jekyll.yml | 12 +++--- Gemfile | 9 +++++ Gemfile.lock | 75 ++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 6 deletions(-) diff --git a/.github/workflows/jekyll.yml b/.github/workflows/jekyll.yml index 52728c3..912942c 100644 --- a/.github/workflows/jekyll.yml +++ b/.github/workflows/jekyll.yml @@ -32,16 +32,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Ruby - uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0 + uses: ruby/setup-ruby@8575951200e472d5f2d95c625da0c7bec8217c42 # v1.161.0 with: - ruby-version: '3.1' # Not needed with a .ruby-version file + # Uses the .ruby-version specified in the root directory bundler-cache: true # runs 'bundle install' and caches installed gems automatically cache-version: 0 # Increment this number if you need to re-download cached gems - name: Setup Pages id: pages - uses: actions/configure-pages@v3 + uses: actions/configure-pages@v5 - name: Build with Jekyll # Outputs to the './_site' directory by default run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" @@ -49,7 +49,7 @@ jobs: JEKYLL_ENV: production - name: Upload artifact # Automatically uploads an artifact from the './_site' directory by default - uses: actions/upload-pages-artifact@v2 + uses: actions/upload-pages-artifact@v3 # Deployment job deploy: @@ -61,4 +61,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v2 + uses: actions/deploy-pages@v4 diff --git a/Gemfile b/Gemfile index ffd27f7..97e2d53 100644 --- a/Gemfile +++ b/Gemfile @@ -37,3 +37,12 @@ group :jekyll_plugins do gem "jekyll-sitemap" gem "jekyll-seo-tag" end + +group :development, :test do + gem "rspec" + gem "selenium-webdriver" + gem "capybara" + gem "rack-jekyll" + gem "axe-core-rspec" + gem "axe-core-capybara" +end diff --git a/Gemfile.lock b/Gemfile.lock index 7f725ee..35ec564 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,9 +3,38 @@ GEM specs: addressable (2.8.5) public_suffix (>= 2.0.2, < 6.0) + axe-core-api (4.9.1) + dumb_delegator + virtus + axe-core-capybara (4.9.1) + axe-core-api (= 4.9.1) + dumb_delegator + axe-core-rspec (4.9.1) + axe-core-api (= 4.9.1) + dumb_delegator + virtus + axiom-types (0.1.1) + descendants_tracker (~> 0.0.4) + ice_nine (~> 0.11.0) + thread_safe (~> 0.3, >= 0.3.1) base64 (0.1.1) + capybara (3.40.0) + addressable + matrix + mini_mime (>= 0.1.3) + nokogiri (~> 1.11) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + coercible (1.0.0) + descendants_tracker (~> 0.0.1) colorator (1.1.0) concurrent-ruby (1.2.2) + descendants_tracker (0.0.4) + thread_safe (~> 0.3, >= 0.3.1) + diff-lcs (1.5.1) + dumb_delegator (1.0.0) em-websocket (0.5.3) eventmachine (>= 0.12.9) http_parser.rb (~> 0) @@ -23,6 +52,7 @@ GEM http_parser.rb (0.8.0) i18n (1.14.1) concurrent-ruby (~> 1.0) + ice_nine (0.11.2) jekyll (4.3.2) addressable (~> 2.4) colorator (~> 1.0) @@ -61,20 +91,47 @@ GEM listen (3.8.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) + matrix (0.4.2) mercenary (0.4.0) + mini_mime (1.1.5) + nokogiri (1.16.6-arm64-darwin) + racc (~> 1.4) octokit (4.25.1) faraday (>= 1, < 3) sawyer (~> 0.9) pathutil (0.16.2) forwardable-extended (~> 2.6) public_suffix (5.0.3) + racc (1.8.0) + rack (1.6.13) + rack-jekyll (0.5.0) + jekyll (>= 1.3) + listen (>= 1.3) + rack (~> 1.5) + rack-test (2.1.0) + rack (>= 1.3) rake (13.0.6) rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) + regexp_parser (2.9.2) rexml (3.2.6) rouge (4.1.3) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.0) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.1) ruby2_keywords (0.0.5) + rubyzip (2.3.2) safe_yaml (1.0.5) sass-embedded (1.62.1) google-protobuf (~> 3.21) @@ -84,16 +141,31 @@ GEM sawyer (0.9.2) addressable (>= 2.3.5) faraday (>= 0.17.3, < 3) + selenium-webdriver (4.14.0) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) + thread_safe (0.3.6) unicode-display_width (2.4.2) + virtus (2.0.0) + axiom-types (~> 0.1) + coercible (~> 1.0) + descendants_tracker (~> 0.0, >= 0.0.3) webrick (1.8.1) + websocket (1.2.10) + xpath (3.2.0) + nokogiri (~> 1.8) PLATFORMS ruby x64-mingw32 DEPENDENCIES + axe-core-capybara + axe-core-rspec + capybara jekyll (~> 4) jekyll-feed jekyll-github-metadata (~> 1.0) @@ -102,6 +174,9 @@ DEPENDENCIES jekyll-sitemap kramdown kramdown-parser-gfm + rack-jekyll + rspec + selenium-webdriver webrick RUBY VERSION From 6c769cf5d96b09236433d530254b500372a2f638 Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 13:54:12 -0700 Subject: [PATCH 02/16] WIP setting up accessibility specs for all pages... --- .github/workflows/specs.yml | 19 ++++++++ _config.yml | 8 ++-- spec/accessibility_spec.rb | 44 +++++++++++++++++++ spec/spec_helper.rb | 86 +++++++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/specs.yml create mode 100644 spec/accessibility_spec.rb create mode 100644 spec/spec_helper.rb diff --git a/.github/workflows/specs.yml b/.github/workflows/specs.yml new file mode 100644 index 0000000..717eb34 --- /dev/null +++ b/.github/workflows/specs.yml @@ -0,0 +1,19 @@ +name: Run rspec tests + +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: ruby/setup-ruby@v1 + with: + # Use the .ruby-version file in the repository + # runs 'bundle install' and caches installed gems automatically + bundler-cache: true + # TODO: Setup 'optional' a11y specs, in addition to required ones. + - name: Run rspec tests + run: | + bundle exec rspec diff --git a/_config.yml b/_config.yml index 8fef144..c4f3a82 100644 --- a/_config.yml +++ b/_config.yml @@ -20,7 +20,7 @@ description: > The Beauty and Joy of Computing is an endorsed AP Computer Science Principles course that is a rigorous introduction to programming and that the ways we interact with and are affected by technology every day. keywords: > AP CSP, advanced placement, computer scince principles, comp sci, snap, - programming, computing, BJC, computer science, cs10, bjcx, bjc4nyc + programming, computing, BJC, computer science, cs10, bjcx, bjc4nyc, BJC Sparks, middle school, robotics, baseurl: "" # NOTE: This URL is needed for Github pages. It will get overriden # in the build scripts. @@ -32,7 +32,7 @@ permalink: pretty # This is used for displaying a warning on sites that aren't the # production site. production_url: https://bjc.berkeley.edu -twitter_username: cspbjc +# twitter_username: cspbjc facebook_username: cspbjc instagram_username: cspbjc flipboard_link: https://bjc.link/computingnews @@ -49,17 +49,16 @@ lang: en_US social: name: The Beauty and Joy of Computing links: - - https://twitter.com/cspbjc - https://www.facebook.com/cspbjc - https://github.com/beautyjoy - https://instagram.com/cspbjc google_site_verification: KuWL2ZXn4a2LNuAH4B-ghSObfCQ3tI6yXiSIRo6f05k" -# These are specifically whitelisted by Github plugins: - jekyll-redirect-from - jekyll-feed - jekyll-seo-tag + - jekyll-sitemap # Build settings markdown: kramdown @@ -75,3 +74,4 @@ exclude: - .* - .github - .devcontainer + - spec diff --git a/spec/accessibility_spec.rb b/spec/accessibility_spec.rb new file mode 100644 index 0000000..97d5171 --- /dev/null +++ b/spec/accessibility_spec.rb @@ -0,0 +1,44 @@ +# Run accessibility specs for all pages in the webiste. +# This runs the axe accessibility checker on each page in a headless browser. +# This assumes that the website is running locally on port 4000. + +# TODO: See if we can share this with spec_helper.rb +require 'yaml' +require 'spec_helper' + +# RSPEC_CONFIG_FILE = '_config.yml' or ENV['RSPEC_CONFIG_FILE'] + +def site_url + YAML.load_file(RSPEC_CONFIG_FILE)['url'] +end + +def load_site_urls + deploy_url = site_url + # TODO: Handle case where build is not in _site + sitemap_text = File.read('_site/sitemap.xml') + sitemap_links = sitemap_text.scan(/.+<\/loc>/) + sitemap_links.filter_map do |link| + link = link.gsub("#{deploy_url}", '') + link = link.gsub('', '') + + next unless link.end_with?('.html') or link.end_with?('/') + + link + end +end + +$ALL_PAGES = load_site_urls + +$ALL_PAGES.each do |page| + describe "Page #{page} is accessible", type: :feature, js: true do + before(:each) do + visit(page) + end + + it "according to WCAG 2.0 AA (REQUIRED)" do + expect(page).to be_axe_clean.according_to( + :wcag2aa, "path: #{page} does NOT meet WCAG 2.0 AA standards" + ) + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..866fddc --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,86 @@ +# This file was generated by the `rspec --init` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause +# this file to always be loaded, without a need to explicitly require it in any +# files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need +# it. +# +# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration + +require 'rspec' +require 'capybara/rspec' +require 'rack/jekyll' +require 'rack/test' +require 'axe-rspec' +require 'axe-capybara' + +RSPEC_CONFIG_FILE = '_config.yml' or ENV['RSPEC_CONFIG_FILE'] + +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + + # This option will default to `:apply_to_host_groups` in RSpec 4 (and will + # have no way to turn it off -- the option exists only for backwards + # compatibility in RSpec 3). It causes shared context metadata to be + # inherited by the metadata hash of host groups and examples, rather than + # triggering implicit auto-inclusion in groups with matching metadata. + config.shared_context_metadata_behavior = :apply_to_host_groups + + 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 + options.add_argument('--window-size=1280,800') + + Capybara::Selenium::Driver.new(app, browser: :chrome, options: options) + end + + # Change default_driver to :selenium_chrome if you want to actually see the tests running in a browser locally. + # Should be :chrome_headless in CI though. + Capybara.default_driver = :chrome_headless + Capybara.javascript_driver = :chrome_headless + + # Configure Capybara to load the website through rack-jekyll. + # (force_build: true) builds the site before the tests are run, + # so our tests are always running against the latest version + # of our jekyll site. + # TODO: Update this to expose _config.yml + jekyll_app = Rack::Jekyll.new(force_build: true, config: RSPEC_CONFIG_FILE) + + # https://stackoverflow.com/questions/52506822/testing-a-jekyll-site-with-rspec-and-capybara-getting-a-bizarre-race-case-on-rs + sleep 0.1 while jekyll_app.compiling? + + Capybara.app = jekyll_app + + # Configure Capybara server (otherwise it will error and say to use webrick or puma) + Capybara.server = :webrick + + config.include Capybara::DSL +end From ea4ed18ca694f0bf8deba824ce48c4b8f39f47ec Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 14:08:08 -0700 Subject: [PATCH 03/16] Accessibility specs correctly run on all pages with useful output --- spec/accessibility_spec.rb | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/spec/accessibility_spec.rb b/spec/accessibility_spec.rb index 97d5171..8611c8e 100644 --- a/spec/accessibility_spec.rb +++ b/spec/accessibility_spec.rb @@ -1,43 +1,44 @@ # Run accessibility specs for all pages in the webiste. # This runs the axe accessibility checker on each page in a headless browser. -# This assumes that the website is running locally on port 4000. -# TODO: See if we can share this with spec_helper.rb +# spec_helper ensures the webiste is built and can be served locally + require 'yaml' require 'spec_helper' # RSPEC_CONFIG_FILE = '_config.yml' or ENV['RSPEC_CONFIG_FILE'] def site_url - YAML.load_file(RSPEC_CONFIG_FILE)['url'] + @site_url ||= YAML.load_file(RSPEC_CONFIG_FILE)['url'] end def load_site_urls - deploy_url = site_url + puts "Running accessibility tests, expected deploy URL: #{site_url}" # TODO: Handle case where build is not in _site sitemap_text = File.read('_site/sitemap.xml') sitemap_links = sitemap_text.scan(/.+<\/loc>/) sitemap_links.filter_map do |link| - link = link.gsub("#{deploy_url}", '') - link = link.gsub('', '') + link = link.gsub("#{site_url}", '').gsub('', '') next unless link.end_with?('.html') or link.end_with?('/') link - end + end.sort end -$ALL_PAGES = load_site_urls +ALL_PAGES = load_site_urls +puts "Running tests on #{ALL_PAGES.count} pages." +puts "\t- #{ALL_PAGES.join("\n\t- ")}\n#{'=' * 50}\n\n" -$ALL_PAGES.each do |page| - describe "Page #{page} is accessible", type: :feature, js: true do +ALL_PAGES.each do |path| + describe "Page '#{path}' is accessible", type: :feature, js: true do before(:each) do - visit(page) + visit(path) end it "according to WCAG 2.0 AA (REQUIRED)" do expect(page).to be_axe_clean.according_to( - :wcag2aa, "path: #{page} does NOT meet WCAG 2.0 AA standards" + :wcag2aa, "path: #{path} does NOT meet WCAG 2.0 AA standards" ) end end From 142e425d0293ab2ad46cd76e342e490449ebd649 Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 14:12:51 -0700 Subject: [PATCH 04/16] delint --- Gemfile | 36 +++++++++++++++++++----------------- spec/accessibility_spec.rb | 8 +++++--- spec/spec_helper.rb | 4 +++- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/Gemfile b/Gemfile index 97e2d53..9643246 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,8 @@ -source "https://rubygems.org" +# frozen_string_literal: true -ruby "~> 3" +source 'https://rubygems.org' + +ruby '~> 3' # Hello! This is where you manage which Jekyll version is used to run. # When you want to use a different version, change it below, save the @@ -11,12 +13,12 @@ ruby "~> 3" # This will help ensure the proper Jekyll version is running. # Happy Jekylling! -gem "jekyll", "~> 4" -gem "kramdown" -gem "kramdown-parser-gfm" +gem 'jekyll', '~> 4' +gem 'kramdown' +gem 'kramdown-parser-gfm' # Needed for Ruby 3, Jekyll < 4 -gem "webrick" +gem 'webrick' # Used for syncing content with aws # aws.cs10.org is a backup site @@ -31,18 +33,18 @@ gem "webrick" # If you have any plugins, put them here! group :jekyll_plugins do - gem "jekyll-github-metadata", "~> 1.0" - gem "jekyll-redirect-from" - gem "jekyll-feed" - gem "jekyll-sitemap" - gem "jekyll-seo-tag" + gem 'jekyll-feed' + gem 'jekyll-github-metadata', '~> 1.0' + gem 'jekyll-redirect-from' + gem 'jekyll-seo-tag' + gem 'jekyll-sitemap' end group :development, :test do - gem "rspec" - gem "selenium-webdriver" - gem "capybara" - gem "rack-jekyll" - gem "axe-core-rspec" - gem "axe-core-capybara" + gem 'axe-core-capybara' + gem 'axe-core-rspec' + gem 'capybara' + gem 'rack-jekyll' + gem 'rspec' + gem 'selenium-webdriver' end diff --git a/spec/accessibility_spec.rb b/spec/accessibility_spec.rb index 8611c8e..d6f5a38 100644 --- a/spec/accessibility_spec.rb +++ b/spec/accessibility_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Run accessibility specs for all pages in the webiste. # This runs the axe accessibility checker on each page in a headless browser. @@ -16,11 +18,11 @@ def load_site_urls puts "Running accessibility tests, expected deploy URL: #{site_url}" # TODO: Handle case where build is not in _site sitemap_text = File.read('_site/sitemap.xml') - sitemap_links = sitemap_text.scan(/.+<\/loc>/) + sitemap_links = sitemap_text.scan(%r{.+}) sitemap_links.filter_map do |link| link = link.gsub("#{site_url}", '').gsub('', '') - next unless link.end_with?('.html') or link.end_with?('/') + next unless link.end_with?('.html') || link.end_with?('/') link end.sort @@ -36,7 +38,7 @@ def load_site_urls visit(path) end - it "according to WCAG 2.0 AA (REQUIRED)" do + it 'according to WCAG 2.0 AA (REQUIRED)' do expect(page).to be_axe_clean.according_to( :wcag2aa, "path: #{path} does NOT meet WCAG 2.0 AA standards" ) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 866fddc..e58b134 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file was generated by the `rspec --init` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. # The generated `.rspec` file contains `--require spec_helper` which will cause @@ -59,7 +61,7 @@ # macbook air ~13" screen size options.add_argument('--window-size=1280,800') - Capybara::Selenium::Driver.new(app, browser: :chrome, options: options) + Capybara::Selenium::Driver.new(app, browser: :chrome, options:) end # Change default_driver to :selenium_chrome if you want to actually see the tests running in a browser locally. From ffd6be745ea7822b09701981e5379346ec1c3587 Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 14:28:15 -0700 Subject: [PATCH 05/16] delint a11y spec --- spec/accessibility_spec.rb | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/spec/accessibility_spec.rb b/spec/accessibility_spec.rb index d6f5a38..1d675b1 100644 --- a/spec/accessibility_spec.rb +++ b/spec/accessibility_spec.rb @@ -8,8 +8,6 @@ require 'yaml' require 'spec_helper' -# RSPEC_CONFIG_FILE = '_config.yml' or ENV['RSPEC_CONFIG_FILE'] - def site_url @site_url ||= YAML.load_file(RSPEC_CONFIG_FILE)['url'] end @@ -32,16 +30,34 @@ def load_site_urls puts "Running tests on #{ALL_PAGES.count} pages." puts "\t- #{ALL_PAGES.join("\n\t- ")}\n#{'=' * 50}\n\n" +required_a11y_standards = %i[wcag2a wcag2aa 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 +skipped_rules = [] +# These are elements that are not required to be accessible +excluded_elements = [] + +# These are currently skipped until the basic tests are passing. +complete_a11y_standards = %i[wcag21 best_practice wcag22] + ALL_PAGES.each do |path| describe "Page '#{path}' is accessible", type: :feature, js: true do before(:each) do visit(path) end - it 'according to WCAG 2.0 AA (REQUIRED)' do - expect(page).to be_axe_clean.according_to( - :wcag2aa, "path: #{path} does NOT meet WCAG 2.0 AA standards" - ) + it 'according to WCAG 2.0 AA' do + expect(page).to be_axe_clean + .according_to(*required_a11y_standards, "#{path} does NOT meet WCAG 2.0 AA") + .skipping(*skipped_rules) + .excluding(*excluded_elements) + end + + xit 'according to WCAG 2.2 AA' do + expect(page).to be_axe_clean + .according_to(*complete_a11y_standards) + .skipping(*skipped_rules) + .excluding(*excluded_elements) end end end From c0fe3abd6e91f2ff63e058d181483191c14a6835 Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 15:48:22 -0700 Subject: [PATCH 06/16] cleanup accessibility specs --- spec/accessibility_spec.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/spec/accessibility_spec.rb b/spec/accessibility_spec.rb index 1d675b1..e5581ee 100644 --- a/spec/accessibility_spec.rb +++ b/spec/accessibility_spec.rb @@ -30,16 +30,18 @@ def load_site_urls puts "Running tests on #{ALL_PAGES.count} pages." puts "\t- #{ALL_PAGES.join("\n\t- ")}\n#{'=' * 50}\n\n" -required_a11y_standards = %i[wcag2a wcag2aa section508] +# 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] +# These are currently skipped until the basic tests are passing. +complete_a11y_standards = %i[wcag21a wcag21 wcag22aa best-practice secion508] + # 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 skipped_rules = [] # These are elements that are not required to be accessible excluded_elements = [] -# These are currently skipped until the basic tests are passing. -complete_a11y_standards = %i[wcag21 best_practice wcag22] - ALL_PAGES.each do |path| describe "Page '#{path}' is accessible", type: :feature, js: true do before(:each) do From 69bbb712b1319df240dbb0db819b371ebbca1ff1 Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 15:50:30 -0700 Subject: [PATCH 07/16] tidy a11y spec output --- spec/accessibility_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/accessibility_spec.rb b/spec/accessibility_spec.rb index e5581ee..878fe51 100644 --- a/spec/accessibility_spec.rb +++ b/spec/accessibility_spec.rb @@ -43,7 +43,7 @@ def load_site_urls excluded_elements = [] ALL_PAGES.each do |path| - describe "Page '#{path}' is accessible", type: :feature, js: true do + describe "'#{path}' is accessible", type: :feature, js: true do before(:each) do visit(path) end From d1c2bb1ea335b092d4e59a8d81a4006f89fb3f48 Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 15:50:39 -0700 Subject: [PATCH 08/16] WIP resolve color contrast issues --- assets/css/styles.scss | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/assets/css/styles.scss b/assets/css/styles.scss index 2db4804..f082748 100644 --- a/assets/css/styles.scss +++ b/assets/css/styles.scss @@ -2,8 +2,9 @@ --- // Color scheme: https://color.adobe.com/Collioure-late-evening-color-theme-8618292/ -$primary-color: #18568C; +$_dummy: ''; // this line is included so vscode renders next variable correctly $dark-color: #0C3559; +$primary-color: $dark-color; $accent-color: #F2E205; $accent-dark: #BF7E04; $accent-darker: #8C4E03; @@ -40,10 +41,14 @@ h1, h2, h3, h4, h5, h6 { font-family: $header-font-stack; font-weight: 900; margin-bottom: 20px; + + & a { + text-decoration: none; + } } a, p, li, td { - font-weight: lighter; + // font-weight: lighter; font-family: $body-font-stack; line-height: 1.5em; @@ -65,8 +70,16 @@ ol, ul { } a { + color: $dark-color; + text-decoration: underline; + + &.btn { + text-decoration: none; + } + &.unstyled-link { color: inherit; + text-decoration: none; &:hover, &:focus { color: inherit; @@ -313,8 +326,10 @@ blockquote { } .jumbotron & { - border: 2px white solid; - background: rgba(255, 255, 255, 0.4); + border: 2.5px white solid; + border-radius: 6px; + // background: rgba(255, 255, 255, 0.4); + backdrop-filter: blur(4px) brightness(0.4); } .section & { From 48e632426fe06a776eb6b79b5bc6face9de5ed9b Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 16:09:33 -0700 Subject: [PATCH 09/16] WIP resolve accessibility issues with images in template, index, curr pages --- _includes/footer.html | 24 +++++++++--------------- contact.html | 13 +++++++------ curriculum.html | 43 ++++++++++++++++++++++++++++--------------- index.html | 2 +- 4 files changed, 45 insertions(+), 37 deletions(-) diff --git a/_includes/footer.html b/_includes/footer.html index a46fe07..61ae22c 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -2,26 +2,20 @@
diff --git a/contact.html b/contact.html index e566cc8..dee353b 100644 --- a/contact.html +++ b/contact.html @@ -19,15 +19,16 @@ [{{ site.email }}](mailto:{{ site.email }}) ## Social Profiles + diff --git a/curriculum.html b/curriculum.html index 528a57e..2adae97 100644 --- a/curriculum.html +++ b/curriculum.html @@ -52,7 +52,8 @@

Computer Science Principles

(things to do):

- + Pie Chart of 6 CSP Big Ideas (explained below)

Every conforming curriculum must teach all of these, but curricula may @@ -75,7 +76,7 @@

Computer Science Principles

interested in programming, because it combines the ease of use of visual programming with expressive power previously found only in the most sophisticated text-based languages. (More on this below.) We go far beyond the CS Principles requirements, + href="#visual">below.) We go far beyond the CS Principles requirements, featuring the advanced techniques of recursion and higher order functions.

@@ -159,7 +160,8 @@

Visual Programming

the block categories.

- + Snap! programing showing how to draw a sqaure using repeat

The C-shaped block is a loop, and visually encloses the code that should be @@ -179,9 +181,12 @@

Visual Programming

- - - + Snap! make a block dialog + Snap! block editor dialog + Snap! script using when green flag clicked

This capability is essential to the Abstraction big idea, but it @@ -190,8 +195,10 @@

Visual Programming

- - + Snap! Script of a `tree` block to draw a fractal + A tree fractal drawn by the tree block

Because Snap! blocks can take other blocks or scripts as @@ -201,7 +208,8 @@

Visual Programming

- + Snap! Code: map plus 4 over a list of 3 numbers

This capability, first class procedures, makes Snap! more powerful @@ -211,7 +219,8 @@

Visual Programming

- + 3 blocks inside a Snap! list


@@ -222,7 +231,8 @@

Visual Programming

- + A Snap! program showing a list of 3 items using the point block


@@ -233,11 +243,12 @@

Visual Programming

- + A Snap! speach to text block using JavaScript

(The picture shows a one-liner, but there is no limit to the length or - complexity of the Javascript function defined by the block.) With this + complexity of the Javascript function defined by the block.) With this capability we can have our cake and eat it too, with respect to the (pointless, we think) argument about block languages vs. text languages. We don't teach Javascript in BJC, but it's available as an enrichment @@ -283,7 +294,8 @@

Social Implications of Computing

- + Cover of the Blown to Bits book

In all of these topics, our goal is to avoid preaching; we look for @@ -327,7 +339,8 @@

Social Implications of Computing

About Snap!

diff --git a/index.html b/index.html index f6505a2..d3cc573 100644 --- a/index.html +++ b/index.html @@ -20,7 +20,7 @@

The Beauty and Joy of Computing

- +

The Beauty and Joy of Computing (BJC) is an introductory computer science curriculum developed at the University of California, Berkeley, From 041743d8281666af7629c28526ff0fa15186c222 Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 17:35:01 -0700 Subject: [PATCH 10/16] further enhancements to accessibility specs Elements can be excludes from test cases with the attribute data-a11y-external-errors="true" --- .gitignore | 1 + spec/accessibility_spec.rb | 8 ++++++-- spec/spec_helper.rb | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index de53ee3..9c9a69c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ _berkeley .sass-cache .jekyll-metadata sync.err +tmp/ diff --git a/spec/accessibility_spec.rb b/spec/accessibility_spec.rb index 878fe51..f02d5e2 100644 --- a/spec/accessibility_spec.rb +++ b/spec/accessibility_spec.rb @@ -40,7 +40,9 @@ def load_site_urls # 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 -excluded_elements = [] +excluded_elements = [ + '[data-a11y-external-errors="true"]' +] ALL_PAGES.each do |path| describe "'#{path}' is accessible", type: :feature, js: true do @@ -48,6 +50,7 @@ def load_site_urls visit(path) end + # These tests should always be enabled. it 'according to WCAG 2.0 AA' do expect(page).to be_axe_clean .according_to(*required_a11y_standards, "#{path} does NOT meet WCAG 2.0 AA") @@ -55,7 +58,8 @@ def load_site_urls .excluding(*excluded_elements) end - xit 'according to WCAG 2.2 AA' do + # Berkeley: (June 2024) these tests are skipped until the basic tests are passing. + it 'according to WCAG 2.2 AA', :skip do expect(page).to be_axe_clean .according_to(*complete_a11y_standards) .skipping(*skipped_rules) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e58b134..eacec29 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -26,6 +26,10 @@ RSPEC_CONFIG_FILE = '_config.yml' or ENV['RSPEC_CONFIG_FILE'] RSpec.configure do |config| + # Allow rspec to use `--only-failures` and `--next-failure` flags + # Ensure that `tmp` is in your `.gitignore` file + config.example_status_persistence_file_path = 'tmp/rspec-failures.txt' + # rspec-expectations config goes here. You can use an alternate # assertion/expectation library such as wrong or the stdlib/minitest # assertions if you prefer. From 5584ea04ae8a3b8860b61bc3c3e6eac56507bc16 Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 17:35:12 -0700 Subject: [PATCH 11/16] Further passing some accessibility tests... --- _layouts/post.html | 10 +++++----- edx.html | 2 +- payment/canceled.html | 4 +++- payment/payment-sparks.html | 12 +++++++----- research.html | 5 +++-- spec/accessibility_spec.rb | 6 ++++-- spec/spec_helper.rb | 2 ++ 7 files changed, 25 insertions(+), 16 deletions(-) diff --git a/_layouts/post.html b/_layouts/post.html index 520cb85..7173507 100644 --- a/_layouts/post.html +++ b/_layouts/post.html @@ -26,14 +26,14 @@

{{ page.date | date_to_string }}
- - + - - + Add to Flipboard Magazine.
{% endcapture %} -{% include section.html %} \ No newline at end of file +{% include section.html %} diff --git a/edx.html b/edx.html index 87f426e..b34de57 100644 --- a/edx.html +++ b/edx.html @@ -8,7 +8,7 @@

- + edx logo

diff --git a/payment/canceled.html b/payment/canceled.html index 8479671..bfea43e 100644 --- a/payment/canceled.html +++ b/payment/canceled.html @@ -14,7 +14,7 @@

- +

Your payment was canceled.

@@ -27,6 +27,8 @@

Checkout Session ID:

src="/assets/img/alonzo-canceled.png" width="400" height="300" + alt="" + aria-hidden="true" />
diff --git a/payment/payment-sparks.html b/payment/payment-sparks.html index db44f9e..61267a9 100644 --- a/payment/payment-sparks.html +++ b/payment/payment-sparks.html @@ -25,11 +25,13 @@

Summer Sparks PD Registration Fee

- - +
+ + +
{% endcapture %} {% include section.html %} diff --git a/research.html b/research.html index 94229c4..036a1a4 100644 --- a/research.html +++ b/research.html @@ -25,7 +25,8 @@
{% capture section_content %}

Our "FRABJOUS CS" (Framing a @@ -41,4 +42,4 @@

{% endcapture %} -{% include section.html %} \ No newline at end of file +{% include section.html %} diff --git a/spec/accessibility_spec.rb b/spec/accessibility_spec.rb index f02d5e2..eb105b7 100644 --- a/spec/accessibility_spec.rb +++ b/spec/accessibility_spec.rb @@ -19,7 +19,9 @@ def load_site_urls sitemap_links = sitemap_text.scan(%r{.+}) sitemap_links.filter_map do |link| link = link.gsub("#{site_url}", '').gsub('', '') - + # 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 @@ -28,7 +30,7 @@ def load_site_urls ALL_PAGES = load_site_urls puts "Running tests on #{ALL_PAGES.count} pages." -puts "\t- #{ALL_PAGES.join("\n\t- ")}\n#{'=' * 50}\n\n" +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 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index eacec29..a9c5f30 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -17,6 +17,8 @@ # See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration require 'rspec' +require 'yaml' + require 'capybara/rspec' require 'rack/jekyll' require 'rack/test' From a38de518b3df3a56b9b026924e2f87154e213ee6 Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 17:42:39 -0700 Subject: [PATCH 12/16] Move yaml require line to spec helper --- spec/accessibility_spec.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/accessibility_spec.rb b/spec/accessibility_spec.rb index eb105b7..6ab9b06 100644 --- a/spec/accessibility_spec.rb +++ b/spec/accessibility_spec.rb @@ -4,8 +4,6 @@ # This runs the axe accessibility checker on each page in a headless browser. # spec_helper ensures the webiste is built and can be served locally - -require 'yaml' require 'spec_helper' def site_url From 6cda24a8ab47894aa28b11f9e485ae84252f043d Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Mon, 17 Jun 2024 17:48:50 -0700 Subject: [PATCH 13/16] a11y: resolve images, nav-pills issues --- _layouts/india.html | 8 ++++---- _layouts/pd-6-weeks.html | 4 ++-- _layouts/summer-pd.html | 12 ++++++------ resources.html | 7 ++++--- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/_layouts/india.html b/_layouts/india.html index afae70b..7379e26 100644 --- a/_layouts/india.html +++ b/_layouts/india.html @@ -5,7 +5,7 @@ .jumbotron1 { position: relative; margin: 0; - display: inline-table; + display: inline-table; background: $primary-color; box-shadow: none; background-position: center; @@ -47,7 +47,7 @@ h1 { font-size: 48px; text-transform: uppercase; - word-wrap: break-word; + word-wrap: break-word; }
@@ -61,12 +61,12 @@

BJC India Chapter