diff --git a/.github/ISSUE_TEMPLATE/ACCESSIBILITY_SUPPORT.md b/.github/ISSUE_TEMPLATE/ACCESSIBILITY_SUPPORT.md new file mode 100644 index 00000000000..398f445bf92 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/ACCESSIBILITY_SUPPORT.md @@ -0,0 +1,84 @@ +--- +name: Accessibility support template +about: Issue for tracking accessibility support on ACT Rules +title: '' +labels: ['accessibility support'] +assignees: '' +--- + +## Accessibility support + +(( Put the accessibility support item here )) + +## ACT Rules + +- ... List the rules here, link to its acc support section + +## Test cases + +### Test case 1 ... + +(( Add test case here )) + +```html +code snippet here +``` + +[Open this test case]() + +(( Add a link to a code pen or other hosted test case. Keep in mind this test case needs to be accessible and persistent. )) + +#### Preconditions + +Before running the test, check your settings. In many cases default settings aren't strictly required and will not impact the results. Use common sense here. If non-default settings are necessary for you, record the settings used in the reported results. + +- Ensure browsers are in the default settings, turn off unnecessary extensions +- Ensure ATs are in the default settings +- Ensure operating system are in default settings +- Ensure software uses the correct version (usually the latest version) + +#### Test instructions + +(( Provide instructions on how to test the test case, this should include: )) + +- Which technologies to use +- Any setting changes necessary to run the test +- Any variation in how to operate the different assistive technologies +- Step by step instructions on how to check the test case +- What the expected results are + +### External links + +(( List any external links to bugs in browsers & AT, WPT, or spec issues. Be sure to open issues in the appropriate repositories. )) + + + +## Test results + +Please report test results in a comment below. Please use the following format: + +```md +## Test case X + +- Date: ... +- Operating system: ..., version ... +- Browser: ..., version ... +- Assistive technology: ..., version ... +- Test result: Passed / Failed (if failed, how was it different from expected?) +``` diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE/rules-issue-template.md similarity index 80% rename from .github/ISSUE_TEMPLATE.md rename to .github/ISSUE_TEMPLATE/rules-issue-template.md index 173a095e5c3..54d7c5fd887 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE/rules-issue-template.md @@ -1,3 +1,12 @@ +--- +name: Rules issue template +about: issues related with ACT Rules +title: '' +labels: '' +assignees: '' + +--- + Please describe the issue with references and relevant examples where necessary. --- or --- diff --git a/.github/scripts/pr-preview.mjs b/.github/scripts/pr-preview.mjs new file mode 100644 index 00000000000..849e52e10fd --- /dev/null +++ b/.github/scripts/pr-preview.mjs @@ -0,0 +1,28 @@ +#!/usr/bin/env zx +import 'zx/globals'; +import { config, cloneWcagActRules, commitAndPush } from './commons.mjs' + +await cloneWcagActRules(config); +await generateProposedRulePages(config); +await generateTestCases(config); +// const commitMessage = (await $`git log -1 --pretty=%B`).stdout; +// await commitAndPush(config, commitMessage); + +async function generateProposedRulePages({ tmpDir, rulesDir, glossaryDir, testAssetsDir }) { + await $`node ./node_modules/act-tools/dist/cli/rule-transform.js \ + --rulesDir "${rulesDir}" \ + --glossaryDir "${glossaryDir}" \ + --testAssetsDir "${testAssetsDir}" \ + --outDir "${tmpDir}" \ + --proposed + `; +} + +async function generateTestCases({ tmpDir, rulesDir, testAssetsDir }) { + await $`node ./node_modules/act-tools/dist/cli/build-examples.js \ + --rulesDir "${rulesDir}" \ + --testAssetsDir "${testAssetsDir}" \ + --outDir "${tmpDir}" \ + --proposed + `; +} diff --git a/.github/workflows/wai-deploy.yml b/.github/workflows/wai-deploy.yml index 5c1b03254bc..0c706438ab1 100644 --- a/.github/workflows/wai-deploy.yml +++ b/.github/workflows/wai-deploy.yml @@ -23,6 +23,9 @@ jobs: - run: git config --global url."https://github.com/".insteadOf ssh://git@github.com/ - name: Install dependencies run: npm ci + # Since we control this we can safely just always use the latest + - name: Install act-tools latest + run: npm install github:act-rules/act-tools#main - name: Configure git run: | git config --global url."https://${{ secrets.WAI_GIT_NAME }}:${{ secrets.WAI_GIT_ACCESS_TOKEN }}@github.com".insteadOf "https://github.com" diff --git a/.gitignore b/.gitignore index 5393e070649..c38b3bcc7fb 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,6 @@ yarn.lock # Tmp build directory wcag-act-rules-tmp/ + +# Local Netlify folder +.netlify diff --git a/__tests__/frontmatter.js b/__tests__/frontmatter.js index 2912e9269b9..55b052699e0 100644 --- a/__tests__/frontmatter.js +++ b/__tests__/frontmatter.js @@ -93,18 +93,22 @@ function validateRuleFrontmatter({ frontmatter }, metaData) { /** * The below check the `values` for every `key - value` pair of accessibility requirements */ - const accRequirementValues = Object.values(accessibility_requirements) - test.each(accRequirementValues)('has expected keys for accessibility requirement: `%p`', accReq => { - expect(accReq).not.toBeNull() - expect(typeof accReq).toBe('object') - const keys = Object.keys(accReq).sort() + const accessibilityReqs = Object.entries(accessibility_requirements).map(([key, value]) => ({ key, value })) + test.each(accessibilityReqs)('has expected keys for accessibility requirement: `%p`', ({ key, value }) => { + expect(value).not.toBeNull() + expect(typeof value).toBe('object') + const keys = Object.keys(value).sort() if (keys.includes('secondary')) { expect(keys.length).toBe(1) - expect(typeof accReq.secondary).toBe('string') + expect(typeof value.secondary).toBe('string') } else { + const requiredProps = ['failed', 'forConformance', 'inapplicable', 'passed'] + if (!/wcag-technique:.*/.test(key) && !/wcag2\d:.*/.test(key)) { + requiredProps.push('title') + } expect(keys.length).toBeGreaterThanOrEqual(4) - expect(keys).toIncludeAllMembers(['failed', 'forConformance', 'inapplicable', 'passed']) + expect(keys).toIncludeAllMembers(requiredProps) } }) } diff --git a/__tests__/spelling-ignore.yml b/__tests__/spelling-ignore.yml index 436581b01bf..106dbb404b5 100644 --- a/__tests__/spelling-ignore.yml +++ b/__tests__/spelling-ignore.yml @@ -239,6 +239,8 @@ - unitless - luminance - disambiguated +- superclass +- grey # Parts of Unicode - 000A @@ -293,3 +295,6 @@ - A-lum-min - B-lum-max - B-lum-min + +#Browsers Internal Roles +- SvgRoot diff --git a/_rules/__tests__/headings.js b/_rules/__tests__/headings.js index eb3da8f5a30..4c02b35e853 100644 --- a/_rules/__tests__/headings.js +++ b/_rules/__tests__/headings.js @@ -58,7 +58,7 @@ describeRule('headings', ruleData => { /** * Check for `required` `h2` headings */ - const requiredH2 = [`Applicability`, `Assumptions`, `Accessibility Support`, `Background`, `Test Cases`] + const requiredH2 = [`Applicability`, `Background`, `Test Cases`] const h2Headings = getHeadingOfDepth(headings, 2) test.each(requiredH2)('has required `h2` - `%s`', heading => { expect(h2Headings).toContain(heading) @@ -67,9 +67,9 @@ describeRule('headings', ruleData => { /** * Check for `required` `h3` headings */ - const requiredH3 = [`Passed`, `Failed`, `Inapplicable`] + const requiredH3 = [`Assumptions`, `Accessibility Support`, `Passed`, `Failed`, `Inapplicable`] const h3Headings = getHeadingOfDepth(headings, 3) - test.each(requiredH3)('has required `h2` - `%s`', heading => { + test.each(requiredH3)('has required `h3` - `%s`', heading => { expect(h3Headings).toContain(heading) }) diff --git a/_rules/aria-attr-defined-5f99a7.md b/_rules/aria-attr-defined-5f99a7.md index cc26dc7185a..294257c0fc2 100755 --- a/_rules/aria-attr-defined-5f99a7.md +++ b/_rules/aria-attr-defined-5f99a7.md @@ -1,6 +1,7 @@ --- id: 5f99a7 name: ARIA attribute is defined in WAI-ARIA +rules_format: 1.1 rule_type: atomic description: | This rule checks that each `aria-` attribute specified is defined in ARIA 1.2. @@ -26,17 +27,17 @@ This rule applies to any attribute that starts with `aria-`. Each target attribute is defined in [WAI-ARIA Specifications][]. -## Assumptions +## Background -There are no assumptions. +The presence of unknown ARIA attributes is often the result of a typo or other developer error. These attributes are ignored by browsers and other assistive technologies. This often means that a state or property which should exist is missing. -## Accessibility Support +### Assumptions -There are no accessibility support issues known. +There are no assumptions. -## Background +### Accessibility Support -The presence of unknown ARIA attributes is often the result of a typo or other developer error. These attributes are ignored by browsers and other assistive technologies. This often means that a state or property which should exist is missing. +There are no accessibility support issues known. ### Bibliography @@ -64,7 +65,7 @@ This `article` element has an `aria-atomic` attribute which is defined in [WAI-A This `div` element with a role of `dialog` has an `aria-modal` attribute which is defined in [WAI-ARIA Specifications][]. ```html -
Contains modal content...
+
Contains modal content...
``` #### Passed Example 3 diff --git a/_rules/aria-hidden-no-focusable-content-6cfa84.md b/_rules/aria-hidden-no-focusable-content-6cfa84.md index dbd62d16329..887398ba5b4 100755 --- a/_rules/aria-hidden-no-focusable-content-6cfa84.md +++ b/_rules/aria-hidden-no-focusable-content-6cfa84.md @@ -1,6 +1,7 @@ --- id: 6cfa84 name: Element with aria-hidden has no content in sequential focus navigation +rules_format: 1.1 rule_type: atomic description: | This rule checks that elements with an `aria-hidden` attribute do not contain elements that are part of the sequential focus navigation and focusable. @@ -11,7 +12,7 @@ accessibility_requirements: passed: further testing needed inapplicable: further testing needed using-aria:fourth: - title: Fourth rule of ARIA use + title: Using ARIA, 2.4 Fourth Rule of ARIA Use forConformance: false failed: not satisfied passed: further testing needed @@ -34,14 +35,6 @@ This rule applies to any element with an `aria-hidden` [attribute value][] of `t None of the target elements has an [inclusive descendant][] in the [flat tree][] that are [focusable][] and part of the [sequential focus navigation][]. -## Assumptions - -Interacting with the page does not result in changing the `aria-hidden` [attribute value][] of target elements. An example of such a situation would be when closing a modal dialog makes previously hidden elements that were not [focusable][] or part of the [sequential focus navigation][] become [focusable][] and part of the [sequential focus navigation][]. - -## Accessibility Support - -Some user agents treat the value of `aria-hidden` attribute as case-sensitive. - ## Background Using `aria-hidden="false"` on a descendant of an element with `aria-hidden="true"` [**does not** expose that element](https://www.w3.org/TR/wai-aria-1.2/#aria-hidden). `aria-hidden="true"` hides itself and all its content from assistive technologies. @@ -52,6 +45,14 @@ An element with an `aria-hidden` attribute set to `true` that is also part of th The 1 second time span introduced in the exception of the definition of [focusable][] is an arbitrary limit which is not included in WCAG. Given that scripts can manage the focus state of elements, testing the focused state of an element consistently would be impractical without a time limit. +### Assumptions + +Interacting with the page does not result in changing the `aria-hidden` [attribute value][] of target elements. An example of such a situation would be when closing a modal dialog makes previously hidden elements that were not [focusable][] or part of the [sequential focus navigation][] become [focusable][] and part of the [sequential focus navigation][]. + +### Accessibility Support + +Some user agents treat the value of `aria-hidden` attribute as case-sensitive. + ### Related rules - [Element with presentational children has no focusable content](https://www.w3.org/WAI/standards-guidelines/act/rules/307n5z/) diff --git a/_rules/aria-required-context-role-ff89c9.md b/_rules/aria-required-context-role-ff89c9.md index 67461d2e92f..a499eef0395 100755 --- a/_rules/aria-required-context-role-ff89c9.md +++ b/_rules/aria-required-context-role-ff89c9.md @@ -1,6 +1,7 @@ --- id: ff89c9 name: ARIA required context role +rules_format: 1.1 rule_type: atomic description: | This rule checks that an element with an explicit semantic role exists inside its required context. @@ -33,16 +34,6 @@ This rule applies to any [HTML or SVG element][] that is [included in the access Each test target is the child in the [accessibility tree][] of an element that has a [semantic role][] that is one of the [required context roles][] of the target element. -## Assumptions - -The rule assumes that the [explicit role][] of the applicable elements is appropriate for their element. I.e. A heading incorrectly marked up with `role="cell"` does not fail [success criterion 1.3.1 Info and Relationships][sc131] for not being in the context of a `row`. Having an inappropriate role is itself an issue under 1.3.1 Info and Relationships, so in either scenario a failure of this rule means this success criterion is not satisfied. - -## Accessibility Support - -- User agents do not all have the same accessibility tree. This can lead to different results for this rule, depending on which accessibility tree is used as input. -- `aria-owns` has limited support in some user agents. -- There exist some combination of popular browsers and assistive technologies who do not announce correctly relationships based on a mix of [implicit][implicit role] and [explicit][explicit role] roles. - ## Background The applicability of this rule is limited to the [WAI-ARIA 1.2 Recommendation][aria 1.2] roles. The [WAI-ARIA Graphics Module][] does not include any [required context roles][]. The [Digital Publishing WAI-ARIA Module (DPUB ARIA) 1.0][dpub 1.0] only has two roles with [required context roles][] (`doc-biblioentry` and `doc-endnote`); both of them have issues with their use of role inheritance, and both of them are deprecated in the [Digital Publishing WAI-ARIA Module (DPUB ARIA) 1.1][dpub 1.1] editor's draft. @@ -57,6 +48,16 @@ This rule is restricted to direct parent-child relation in the [accessibility tr Some user agents try to correct missing [required context roles][] or incorrect [content model][]. This often results, for example, in an isolated list item being presented as part of a one-item list containing only itself. Therefore, most test cases contain several targets to try and circumvent these corrections in order to better demonstrate the issue. +### Assumptions + +The rule assumes that the [explicit role][] of the applicable elements is appropriate for their element. I.e. A heading incorrectly marked up with `role="cell"` does not fail [success criterion 1.3.1 Info and Relationships][sc131] for not being in the context of a `row`. Having an inappropriate role is itself an issue under 1.3.1 Info and Relationships, so in either scenario a failure of this rule means this success criterion is not satisfied. + +### Accessibility Support + +- User agents do not all have the same accessibility tree. This can lead to different results for this rule, depending on which accessibility tree is used as input. +- `aria-owns` has limited support in some user agents. +- There exist some combination of popular browsers and assistive technologies who do not announce correctly relationships based on a mix of [implicit][implicit role] and [explicit][explicit role] roles. + ### Bibliography - [Understanding Success Criterion 1.3.1: Info and Relationships](https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships.html) diff --git a/_rules/aria-required-id-references-in6db8.md b/_rules/aria-required-id-references-in6db8.md index de7401e8cb2..e7682cd415e 100644 --- a/_rules/aria-required-id-references-in6db8.md +++ b/_rules/aria-required-id-references-in6db8.md @@ -1,6 +1,7 @@ --- id: in6db8 name: ARIA required ID references exist +rules_format: 1.1 rule_type: atomic description: | This rule checks that every ID reference required by WAI-ARIA exists @@ -34,17 +35,17 @@ This rule applies to any `aria-controls` attribute defined on an [HTML element][ Each test target's [attribute value][] is a space-separated list of one or more IDs. At least one of those IDs must match an `id` [attribute value][] in the same [shadow tree][] or, if not within a [shadow tree][], within the same [document][document tree]. -## Assumptions +## Background -There are no assumptions. +This rule is written specifically for `aria-controls`, because it is the only [ID Reference List][] property that is [required by WAI-ARIA][]. The `aria-controls` property is only required by the `scrollbar` role and by an expanded `combobox`. There are no [ID Reference][] properties that are required by WAI-ARIA for any role. -## Accessibility Support +### Assumptions -Some user agents treat the value of `aria-*` attribute as case-sensitive (even when these are not IDs) while some treat them as case-insensitive. +There are no assumptions. -## Background +### Accessibility Support -This rule is written specifically for `aria-controls`, because it is the only [ID Reference List][] property that is [required by WAI-ARIA][]. The `aria-controls` property is only required by the `scrollbar` role and by an expanded `combobox`. There are no [ID Reference][] properties that are required by WAI-ARIA for any role. +Some user agents treat the value of `aria-*` attribute as case-sensitive (even when these are not IDs) while some treat them as case-insensitive. ### Bibliography @@ -77,7 +78,7 @@ The `aria-controls` [attribute value][] of this `scrollbar` matches the `id` of The `aria-controls` [attribute value][] of this expanded `combobox` matches the `id` of the `ul` element in the same document. ```html - + -