diff --git a/.circleci/config.yml b/.circleci/config.yml index 6c690fcc1f..d8297be0dc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,113 +1,162 @@ -version: 2 +version: 2.1 defaults: &defaults + working_directory: ~/axe-core + +unix_box: &unix_box docker: - image: circleci/node:10-browsers - working_directory: ~/axe-core -restore_dependency_cache: &restore_dependency_cache +win_box: &win_box + executor: + name: win/vs2019 + shell: bash.exe + +orbs: + win: circleci/windows@1.0.0 + +set_npm_auth: &set_npm_auth + run: npm config set "//registry.npmjs.org/:_authToken" $NPM_AUTH + +restore_dependency_cache_unix: &restore_dependency_cache_unix restore_cache: keys: - - v{{ .Environment.CACHE_VERSION }}-npm-cache-{{ checksum "package.json" }} - - v{{ .Environment.CACHE_VERSION }}-npm-cache- + - v8-cache-unix-{{ checksum "package.json" }} + - v8-cache-unix- -restore_phantomjs_cache: &restore_phantomjs_cache +restore_dependency_cache_win: &restore_dependency_cache_win restore_cache: keys: - - v{{ .Environment.CACHE_VERSION }}-phantomjs-2.1.1 - -set_npm_auth: &set_npm_auth - run: npm config set "//registry.npmjs.org/:_authToken" $NPM_AUTH + - v8-cache-win-{{ checksum "package.json" }} + - v8-cache-win- jobs: # Fetch and cache dependencies. - dependencies: + dependencies_unix: + <<: *defaults + <<: *unix_box + steps: + - checkout + - <<: *set_npm_auth + - <<: *restore_dependency_cache_unix + - run: npm install + - save_cache: + key: v8-cache-unix-{{ checksum "package.json" }} + paths: + - node_modules + dependencies_win: <<: *defaults + <<: *win_box steps: - checkout - <<: *set_npm_auth - - <<: *restore_dependency_cache + - <<: *restore_dependency_cache_win - run: npm install - save_cache: - key: v{{ .Environment.CACHE_VERSION }}-npm-cache-{{ checksum "package.json" }} + key: v8-cache-win-{{ checksum "package.json" }} paths: - node_modules # Run ESLINT lint: <<: *defaults + <<: *unix_box steps: - checkout - - <<: *restore_dependency_cache + - <<: *restore_dependency_cache_unix - run: npm run eslint # Run the test suite. - test: + test_unix: <<: *defaults + <<: *unix_box steps: - checkout - - <<: *restore_dependency_cache - - <<: *restore_phantomjs_cache - - run: - name: PhantomJs - Install or Restore from Cache - command: 'sh .circleci/install-phantomjs.sh' - - save_cache: - key: v{{ .Environment.CACHE_VERSION }}-phantomjs-2.1.1 - paths: - - phantomjs + - <<: *restore_dependency_cache_unix - run: npm run test + + # Run the test suite in IE in windows + test_win: + <<: *defaults + <<: *win_box + steps: + - checkout + # npm i or restore cache + - <<: *restore_dependency_cache_win + # install selenium + - run: | + choco install selenium-ie-driver --version 3.141.5 + export PATH=/c/tools/selenium:$PATH + echo $PATH + # build `axe` + - run: npm run build + # get fixtures ready for running tests + - run: npx grunt testconfig + - run: npx grunt fixture + # run IE webdriver tests + - run: npx grunt connect test-webdriver:ie + # test examples + # Note: Jasmine karma-chrome-launcher requires chrome browser + - run: choco install googlechrome --ignore-checksums + - run: npm run test:examples # Run examples under `doc/examples` test_examples: <<: *defaults + <<: *unix_box steps: - checkout - - <<: *restore_dependency_cache + - <<: *restore_dependency_cache_unix - run: npm run test:examples # Test locale files test_locales: <<: *defaults + <<: *unix_box steps: - checkout - - <<: *restore_dependency_cache + - <<: *restore_dependency_cache_unix - run: npm run build - run: npm run test:locales # Test api docs can be built build_api_docs: <<: *defaults + <<: *unix_box steps: - checkout - - <<: *restore_dependency_cache + - <<: *restore_dependency_cache_unix - run: npm run api-docs # Test newest axe-core version rule help docs are active (only on # master prs) test_rule_help_version: <<: *defaults + <<: *unix_box steps: - checkout - - <<: *restore_dependency_cache + - <<: *restore_dependency_cache_unix - run: npm run test:rule-help-version # Release a "next" version next_release: <<: *defaults + <<: *unix_box steps: - checkout - <<: *set_npm_auth - - <<: *restore_dependency_cache + - <<: *restore_dependency_cache_unix - run: npm run next-release - run: npm publish --tag=next # Release a "production" version release: <<: *defaults + <<: *unix_box steps: - checkout - <<: *set_npm_auth - - <<: *restore_dependency_cache + - <<: *restore_dependency_cache_unix - run: npm run build - run: npm publish @@ -130,33 +179,38 @@ workflows: build: jobs: # install deps - - dependencies + - dependencies_unix + - dependencies_win # Run linting - lint: requires: - - dependencies + - dependencies_unix # Run tests on all commits, but after installing dependencies - - test: + - test_unix: requires: - - dependencies + - dependencies_unix - lint + # Run IE/ Windows test on all commits + - test_win: + requires: + - dependencies_win - test_examples: requires: - - test + - test_unix - test_locales: requires: - - test + - test_unix - build_api_docs: requires: - - test + - test_unix - test_rule_help_version: requires: - - test + - test_unix # Hold for approval - hold: type: approval requires: - - test + - test_unix - test_examples - test_locales - build_api_docs @@ -168,8 +222,8 @@ workflows: # Run a next release on "develop" commits, but only after the tests pass and dependencies are installed - next_release: requires: - - dependencies - - test + - dependencies_unix + - test_unix - test_examples - test_locales - build_api_docs @@ -179,8 +233,8 @@ workflows: # Run a production release on "master" commits, but only after the tests pass and dependencies are installed - release: requires: - - dependencies - - test + - dependencies_unix + - test_unix - test_examples - test_locales - build_api_docs @@ -191,4 +245,4 @@ workflows: only: master - github_release: requires: - - release + - release \ No newline at end of file diff --git a/.circleci/install-phantomjs.sh b/.circleci/install-phantomjs.sh deleted file mode 100644 index 7e2a6ab6db..0000000000 --- a/.circleci/install-phantomjs.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -if [ ! -e phantomjs ]; then - # phantomjs cache does not exist, fetch phantomjs - sudo curl --output phantomjs https://s3.amazonaws.com/circle-downloads/phantomjs-2.1.1 -fi - -# move phantomjs to bin -sudo cp -r phantomjs /usr/local/bin/phantomjs - -# update permissions -sudo chmod ugo+x /usr/local/bin/phantomjs diff --git a/.eslintrc b/.eslintrc index 1f18745554..4e65fd8e65 100644 --- a/.eslintrc +++ b/.eslintrc @@ -43,7 +43,7 @@ 5 ], "no-cond-assign": 0, - "no-debugger": 0, + "no-debugger": 2, "no-eq-null": 0, "no-eval": 0, "no-unused-expressions": 0, diff --git a/.npmignore b/.npmignore index a3e29a0ff2..648ff3a6ba 100644 --- a/.npmignore +++ b/.npmignore @@ -17,7 +17,6 @@ node_modules .prettierignore .prettierrc .retireignore.json -appveyor.yml greenkeeper.json Gruntfile.js tsconfig.json diff --git a/CHANGELOG.md b/CHANGELOG.md index adce62853e..8cf408c756 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,80 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [3.5.0](https://github.com/dequelabs/axe-core/compare/v3.4.0...v3.5.0) (2020-02-04) + +### Features + +- **aria-dpub-role-fallback:** depreacte aria-dpub-role-fallback and move into aria-allowed-role ([#1899](https://github.com/dequelabs/axe-core/issues/1899)) ([8e25c20](https://github.com/dequelabs/axe-core/commit/8e25c20a479b03820117c6cd349b51ce7f2e94ee)) +- **aria-label:** deprecate Element arg; use virtualNode ([#1922](https://github.com/dequelabs/axe-core/issues/1922)) ([d14981c](https://github.com/dequelabs/axe-core/commit/d14981c1f67ba849f9519ee826ac646d281649c7)) +- **audit:** allow runOnly option to accept an array of rules ([#1889](https://github.com/dequelabs/axe-core/issues/1889)) ([38d6a3f](https://github.com/dequelabs/axe-core/commit/38d6a3fb26c66215cca0f3df8da268b34bcb6be5)) +- **color-contrast:** greatly improve performance for very large sites ([#1943](https://github.com/dequelabs/axe-core/issues/1943)) ([9ea0065](https://github.com/dequelabs/axe-core/commit/9ea006534a423b2b7df1826a40e8214c6bb1fc48)) +- **core:** add preload configuration option for media files ([#1958](https://github.com/dequelabs/axe-core/issues/1958)) ([8a62649](https://github.com/dequelabs/axe-core/commit/8a626498dc9694a992e76855781e2ad1cbd4fe9b)) +- **core/reporters/v1:** Add failureSummary to incomplete results ([#1972](https://github.com/dequelabs/axe-core/issues/1972)) ([c88883d](https://github.com/dequelabs/axe-core/commit/c88883d00b6578593b83f3134ebf897d22a3ba61)) +- **get-element-stack:** performant api to replace document.elementsFromPoint ([#1842](https://github.com/dequelabs/axe-core/issues/1842)) ([9ae07fb](https://github.com/dequelabs/axe-core/commit/9ae07fbda36afd18a42a96d6755055006f309a4c)) +- **i18n:** add Danish (da-DK) translation ([#1876](https://github.com/dequelabs/axe-core/issues/1876)) ([fb6fc41](https://github.com/dequelabs/axe-core/commit/fb6fc414246bdaf1590d367352e4bea033822639)) +- **landmark-no-duplicate-\*:** add rule landmark-no-duplicate-main, don't use html as element source for all duplicate rules ([#1949](https://github.com/dequelabs/axe-core/issues/1949)) ([5ec7894](https://github.com/dequelabs/axe-core/commit/5ec7894394f8348761f5fe48ad0d09b31a27d2b2)) +- **layout-table:** deprecate layout-table rule and checks ([#1885](https://github.com/dequelabs/axe-core/issues/1885)) ([d22cb30](https://github.com/dequelabs/axe-core/commit/d22cb30ad29f5d1aec089eea3544ff88f3b4f8ab)) +- **matches:** use VirtualNode and deprecate HTMLElement ([#1988](https://github.com/dequelabs/axe-core/issues/1988)) ([2600a06](https://github.com/dequelabs/axe-core/commit/2600a062d65f0c079b30d6a9f2aa3b6faeea6872)) +- **rule:** add color-contrast check for unicode characters, behind flags. ([#1969](https://github.com/dequelabs/axe-core/issues/1969)) ([0cd4037](https://github.com/dequelabs/axe-core/commit/0cd40373ff9a080ffcb128ce66f9eaf80f0d19b4)), closes [#1906](https://github.com/dequelabs/axe-core/issues/1906) +- **rule:** identical-links-same-purpose ([#1649](https://github.com/dequelabs/axe-core/issues/1649)) ([9c73f62](https://github.com/dequelabs/axe-core/commit/9c73f62fea2be68cb555c36fc32c79f7ce2697dd)) +- **rule:** no-autoplay-audio ([#1946](https://github.com/dequelabs/axe-core/issues/1946)) ([b2373cb](https://github.com/dequelabs/axe-core/commit/b2373cb9ce73a15e79aec86af7edff62c9a4e2b3)) +- **svg-img-alt:** rule for when svg needs a title ([#1953](https://github.com/dequelabs/axe-core/issues/1953)) ([9491e09](https://github.com/dequelabs/axe-core/commit/9491e094fe82c4dba45eb253ed18bf0a0165197c)) +- deprecate the use doT.js for messages ([#1938](https://github.com/dequelabs/axe-core/issues/1938)) ([a2ddba3](https://github.com/dequelabs/axe-core/commit/a2ddba305003db0540c093f4ad9015c8854cd98d)) + +### Bug Fixes + +- **color-contrast:** properly pass options to check ([#2033](https://github.com/dequelabs/axe-core/issues/2033)) ([26b99c0](https://github.com/dequelabs/axe-core/commit/26b99c0a511bd6fffaaca7535d732f26b39ef46e)) +- **commons:** avoid unicode regex encoding in axe.min.js ([#2024](https://github.com/dequelabs/axe-core/issues/2024)) ([ae90dc4](https://github.com/dequelabs/axe-core/commit/ae90dc47521f6047f71befcb3551686cf857208d)) +- add tags with dots for wcag sc ([#1849](https://github.com/dequelabs/axe-core/issues/1849)) ([2f1ab36](https://github.com/dequelabs/axe-core/commit/2f1ab36354add65fe77be3e2831278ce37c3bbab)) +- compute orientation lock from various transformation func… ([#1937](https://github.com/dequelabs/axe-core/issues/1937)) ([c987de0](https://github.com/dequelabs/axe-core/commit/c987de0ce7cfcde5a280a9d6c643879093df1bcd)) +- ignores axe.ping responses that do not contain axe=true ([26cb1fb](https://github.com/dequelabs/axe-core/commit/26cb1fbdd7127c421bb7ca60e07d72385c6e2ea1)) +- input[role=button][value='correct'] should pass ([#1897](https://github.com/dequelabs/axe-core/issues/1897)) ([4635fef](https://github.com/dequelabs/axe-core/commit/4635fef8bafd1c1cf916962693d0deee082266cf)) +- remove heading from list of widget roles ([#1882](https://github.com/dequelabs/axe-core/issues/1882)) ([a8cbf71](https://github.com/dequelabs/axe-core/commit/a8cbf717ef3aa8b0bf09ddcb17f3a95fd2d1a64a)) +- **link-name:** test role=link when there is no href ([#1921](https://github.com/dequelabs/axe-core/issues/1921)) ([6db28bc](https://github.com/dequelabs/axe-core/commit/6db28bc455b1c8937f44346aa232eacc4a1c3457)) +- remove isNaN check ([#2010](https://github.com/dequelabs/axe-core/issues/2010)) ([5359b3f](https://github.com/dequelabs/axe-core/commit/5359b3f06ac051963ee61fcef417bcc20bdec55b)) +- **aria-allowed-attr:** allow aria-details ([#1956](https://github.com/dequelabs/axe-core/issues/1956)) ([79e1c58](https://github.com/dequelabs/axe-core/commit/79e1c58cad4fdbd1409a0b545981c12f13252432)) +- **aria-allowed-role:** allow role combobox on input tel, search, url, and email ([#1850](https://github.com/dequelabs/axe-core/issues/1850)) ([ba75961](https://github.com/dequelabs/axe-core/commit/ba759618ed8068f4eb74b6cd00f002322b20eca5)) +- **aria-hidden-focus:** mark as needs review if a modal is open ([#1995](https://github.com/dequelabs/axe-core/issues/1995)) ([28a3553](https://github.com/dequelabs/axe-core/commit/28a35531b97b987e2fd1ad0beb25fbda3822fbd5)) +- **aria-required-children:** allow comboboxes with more popup roles ([#1950](https://github.com/dequelabs/axe-core/issues/1950)) ([35a24c0](https://github.com/dequelabs/axe-core/commit/35a24c034520e3c6d95514e3b9d9f2ab6ca10e06)) +- **aria-roles:** report error for fallback roles ([#1970](https://github.com/dequelabs/axe-core/issues/1970)) ([a1b7e08](https://github.com/dequelabs/axe-core/commit/a1b7e08f1f8e1c1caff228469cd891d0458680de)) +- **aria-valid-attr-value:** mark as needs review for aria-current with invalid value ([#1998](https://github.com/dequelabs/axe-core/issues/1998)) ([39b8eae](https://github.com/dequelabs/axe-core/commit/39b8eae9d3352be4f77bef41abcb8eab268a6809)) +- **axe.d.ts:** RunOnly.values should not accept a RunOnlyOption ([#1888](https://github.com/dequelabs/axe-core/issues/1888)) ([b68aa19](https://github.com/dequelabs/axe-core/commit/b68aa19500ffb57fdf370707d7614384ac239ad6)) +- **build:** add lang query parameter to helpUrl when builing with a locale ([#1909](https://github.com/dequelabs/axe-core/issues/1909)) ([8c5f9ef](https://github.com/dequelabs/axe-core/commit/8c5f9efd6449f82e410eb7c6a68cfb5304fc66ae)) +- **color-contrast:** improve speed and accuracy of code blocks with syntax highlighting ([#2003](https://github.com/dequelabs/axe-core/issues/2003)) ([1b6ab42](https://github.com/dequelabs/axe-core/commit/1b6ab42f72b1ea0d2ed223c6fd63b9b1e54cfa9b)) +- **color-contrast:** mark as needs review for text that contains only non-BMP characters ([#2005](https://github.com/dequelabs/axe-core/issues/2005)) ([e559be0](https://github.com/dequelabs/axe-core/commit/e559be041e90951c734de4e7ad70d7299f590cf6)) +- **color-contrast:** support IE extension context ([#2008](https://github.com/dequelabs/axe-core/issues/2008)) ([62e31ea](https://github.com/dequelabs/axe-core/commit/62e31ea5034871f572f8bb47dba2596fb1b13063)) +- **color-contrast:** take into account parent opacity for foreground color ([#1902](https://github.com/dequelabs/axe-core/issues/1902)) ([8719700](https://github.com/dequelabs/axe-core/commit/87197005d046cc8c845764ff9107683938864c65)) +- **getElementStack:** do not add hidden elements to the stack ([#1991](https://github.com/dequelabs/axe-core/issues/1991)) ([759d88d](https://github.com/dequelabs/axe-core/commit/759d88d08af059755d908794038770cc57448252)) +- **is-focusable:** use tabindex attribute instead of property ([#1912](https://github.com/dequelabs/axe-core/issues/1912)) ([042a148](https://github.com/dequelabs/axe-core/commit/042a1487df76489483330274933d06fd27b842e0)) +- **is-icon-ligature:** ignore whitespace characters ([#1908](https://github.com/dequelabs/axe-core/issues/1908)) ([7d2b2a6](https://github.com/dequelabs/axe-core/commit/7d2b2a6fca992e27bab36ed8ab64b7ba3385d7e5)) +- **is-ligature-icon:** rename canvas to canvasContext ([#1880](https://github.com/dequelabs/axe-core/issues/1880)) ([de9885d](https://github.com/dequelabs/axe-core/commit/de9885d5708d6928fa2eb2816351879307a31a5b)) +- **isFocusable:** return true for summary element and false for details element with summary child ([#1957](https://github.com/dequelabs/axe-core/issues/1957)) ([34ec2d7](https://github.com/dequelabs/axe-core/commit/34ec2d7326786347f8704786e886fc8d13dd3f9b)) +- **listitem:** clarify that li elements must be contained in a list or role=list ([#1894](https://github.com/dequelabs/axe-core/issues/1894)) ([6d8cfee](https://github.com/dequelabs/axe-core/commit/6d8cfee91f0f0b5dcacba7ffb0b3d6505862e6b7)) +- **locales:** fix incompeteMessageFallback to be a string rather than an object ([#1853](https://github.com/dequelabs/axe-core/issues/1853)) ([88677a9](https://github.com/dequelabs/axe-core/commit/88677a93d0ffe32d7305984314a37e623fb51153)) +- **meta-viewport:** mark as a best-practice rule instead of wcag failure ([#1960](https://github.com/dequelabs/axe-core/issues/1960)) ([766f962](https://github.com/dequelabs/axe-core/commit/766f96210d05d35cab0139839db4f009b1139ce1)) +- **only-listitem:** add message about invalid role on li elements ([#1954](https://github.com/dequelabs/axe-core/issues/1954)) ([c3049ab](https://github.com/dequelabs/axe-core/commit/c3049abaccff72412ec3d58fab9b386fe8a2ae5a)) +- **page-has-main:** do not find hidden elements ([#2001](https://github.com/dequelabs/axe-core/issues/2001)) ([6429e60](https://github.com/dequelabs/axe-core/commit/6429e608f082db76b4cc445679b61a6e0ab8f034)) +- **page-no-duplicate-main:** do not fail for duplicate hidden elements ([#2000](https://github.com/dequelabs/axe-core/issues/2000)) ([414dfb1](https://github.com/dequelabs/axe-core/commit/414dfb1c9a4ade645ce60e8918e8143fe58b3eb6)) +- **preload:** reject promise `axe.utils.preload` when XHR fails ([#2009](https://github.com/dequelabs/axe-core/issues/2009)) ([b406b1f](https://github.com/dequelabs/axe-core/commit/b406b1fd09d72f9193d5b4011fa6f24bd33e3576)) +- **region:** allow content in roles with implicit aria-live ([#2002](https://github.com/dequelabs/axe-core/issues/2002)) ([a8d829e](https://github.com/dequelabs/axe-core/commit/a8d829e081dabb62a5247e8956adbf7a2ef000a2)) +- **region:** return outermost regionless node instead of html ([#1980](https://github.com/dequelabs/axe-core/issues/1980)) ([8d77be2](https://github.com/dequelabs/axe-core/commit/8d77be206e11537e8b509d593707c98143181bfa)) +- **region-rule:** allow live regions with explicit roles ([#1999](https://github.com/dequelabs/axe-core/issues/1999)) ([b49bd95](https://github.com/dequelabs/axe-core/commit/b49bd9547b7d8ac392ebf958356f90aca7e48a38)) +- **run:** throw error if axe.run is called after a run has started but not completed ([#1914](https://github.com/dequelabs/axe-core/issues/1914)) ([3252a02](https://github.com/dequelabs/axe-core/commit/3252a020ffd372e9583d39c989affd3d3b22957b)) +- **server-side-image-map:** return as needs review rather than failure ([#1898](https://github.com/dequelabs/axe-core/issues/1898)) ([d544856](https://github.com/dequelabs/axe-core/commit/d5448567b23de8289443c9c314b34b3140f68c30)) +- **tabindex:** don't error when tabindex property is overridden ([#1910](https://github.com/dequelabs/axe-core/issues/1910)) ([6b82a4c](https://github.com/dequelabs/axe-core/commit/6b82a4c513a1d5be78dcc54ad90a90768613b918)) +- **td-has-headers:** greatly improve performance of td-has-headers rule ([#1887](https://github.com/dequelabs/axe-core/issues/1887)) ([a550309](https://github.com/dequelabs/axe-core/commit/a550309255b025cb1e63710af2142f2c02d79657)) +- removes flaky test in axe Pro api check ([b2bdcd1](https://github.com/dequelabs/axe-core/commit/b2bdcd13e7623d3111f7035f2e951ff6b330132c)) +- **typings:** add proper return value to getRule ([#1900](https://github.com/dequelabs/axe-core/issues/1900)) ([4d907f8](https://github.com/dequelabs/axe-core/commit/4d907f86b0152122f92cceae0b242e09aff0f49a)) +- **unicode:** stop parsing escaped unicode strings ([#1997](https://github.com/dequelabs/axe-core/issues/1997)) ([7447d03](https://github.com/dequelabs/axe-core/commit/7447d03bcfd118897d8114fded1ea8a42f3da08f)) + +## [3.4.2](https://github.com/dequelabs/axe-core/compare/v3.4.1...v3.4.2) (2020-02-04) + +### Bug Fixes + +- **color-contrast:** support IE extension context ([#2008](https://github.com/dequelabs/axe-core/issues/2008)) ([cd651a0](https://github.com/dequelabs/axe-core/commit/cd651a0713fa2f4b307cc7fc2be033f8636b40d2)) +- **unicode:** stop parsing escaped unicode strings ([#1997](https://github.com/dequelabs/axe-core/issues/1997)) ([523a31c](https://github.com/dequelabs/axe-core/commit/523a31c19fefd330e0b4f4c45f51d400c6f66164)) + ### [3.4.1](https://github.com/dequelabs/axe-core/compare/v3.4.0...v3.4.1) (2019-12-11) ### Bug Fixes @@ -66,6 +140,13 @@ All notable changes to this project will be documented in this file. See [standa - **runVirtualNode:** Allow serialised nodes [experimental](<[512d51b](https://github.com/dequelabs/axe-core/commit/512d51b)>) - **video-description:** deprecate video-description rule ([#1737](https://github.com/dequelabs/axe-core/issues/1737)) ([e91c25f](https://github.com/dequelabs/axe-core/commit/e91c25f)) +## [3.3.3](https://github.com/dequelabs/axe-core/compare/v3.3.2...v3.3.3) (2020-02-04) + +### Bug Fixes + +- **color-contrast:** support IE extension context ([#2008](https://github.com/dequelabs/axe-core/issues/2008)) ([cd651a0](https://github.com/dequelabs/axe-core/commit/cd651a0713fa2f4b307cc7fc2be033f8636b40d2)) +- **unicode:** stop parsing escaped unicode strings ([#1997](https://github.com/dequelabs/axe-core/issues/1997)) ([523a31c](https://github.com/dequelabs/axe-core/commit/523a31c19fefd330e0b4f4c45f51d400c6f66164)) + ### [3.3.2](https://github.com/dequelabs/axe-core/compare/v3.3.1...v3.3.2) (2019-08-12) ### Bug Fixes @@ -166,6 +247,13 @@ All notable changes to this project will be documented in this file. See [standa - only run IE11 tests in appveyor ([#1571](https://github.com/dequelabs/axe-core/issues/1571)) ([35261ef](https://github.com/dequelabs/axe-core/commit/35261ef)) - watch integration html and json files ([#1598](https://github.com/dequelabs/axe-core/issues/1598)) ([3de0b05](https://github.com/dequelabs/axe-core/commit/3de0b05)) +## [3.2.3](https://github.com/dequelabs/axe-core/compare/v3.2.2...v3.2.3) (2020-02-04) + +### Bug Fixes + +- **color-contrast:** support IE extension context ([#2008](https://github.com/dequelabs/axe-core/issues/2008)) ([cd651a0](https://github.com/dequelabs/axe-core/commit/cd651a0713fa2f4b307cc7fc2be033f8636b40d2)) +- **unicode:** stop parsing escaped unicode strings ([#1997](https://github.com/dequelabs/axe-core/issues/1997)) ([523a31c](https://github.com/dequelabs/axe-core/commit/523a31c19fefd330e0b4f4c45f51d400c6f66164)) + ## [3.2.2](https://github.com/dequelabs/axe-core/compare/v3.2.0...v3.2.2) (2019-03-07) ### Bug Fixes diff --git a/Gruntfile.js b/Gruntfile.js index 03cd6aa128..72ab91a6ef 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -13,7 +13,6 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-watch'); - grunt.loadNpmTasks('grunt-mocha'); grunt.loadNpmTasks('grunt-parallel'); grunt.loadNpmTasks('grunt-run'); grunt.loadTasks('build/tasks'); @@ -208,6 +207,7 @@ module.exports = function(grunt) { compress: false, beautify: { beautify: true, + ascii_only: true, indent_level: 2, braces: true, quote_style: 1 @@ -252,18 +252,7 @@ module.exports = function(grunt) { }, testconfig: { test: { - src: ['test/integration/rules/**/*.json'].concat( - process.env.APPVEYOR - ? [ - // These tests are causing PhantomJS to timeout on Appveyor - // Warning: PhantomJS timed out, possibly due to a missing Mocha run() call. Use --force to continue. - '!test/integration/rules/td-has-header/*.json', - '!test/integration/rules/label-content-name-mismatch/*.json', - '!test/integration/rules/label/*.json', - '!test/integration/rules/th-has-data-cells/*.json' - ] - : [] - ), + src: ['test/integration/rules/**/*.json'], dest: 'tmp/integration-tests.js' } }, @@ -337,9 +326,6 @@ module.exports = function(grunt) { } } }, - mocha: testConfig(grunt, { - reporter: grunt.option('reporter') || 'Spec' - }), connect: { test: { options: { @@ -353,14 +339,21 @@ module.exports = function(grunt) { npm_run_imports: { cmd: 'node', args: ['./build/imports-generator'] + }, + npm_run_testHeadless: { + cmd: 'npm', + args: ['run', 'test:headless'] } } }); - grunt.registerTask('default', ['build']); - + grunt.registerTask('translate', [ + 'pre-build', + 'validate', + 'concat:commons', + 'add-locale' + ]); grunt.registerTask('pre-build', ['clean', 'run:npm_run_imports']); - grunt.registerTask('build', [ 'pre-build', 'validate', @@ -371,45 +364,20 @@ module.exports = function(grunt) { 'uglify', 'aria-supported' ]); - - grunt.registerTask('test', [ + grunt.registerTask('prepare', [ 'build', 'file-exists', 'testconfig', 'fixture', - 'connect', - 'mocha', - 'parallel' + 'connect' ]); - - grunt.registerTask('ci-build', [ - 'build', - 'testconfig', - 'fixture', - 'connect', + grunt.registerTask('default', ['build']); + grunt.registerTask('dev', ['prepare', 'watch']); + grunt.registerTask('test-fast', ['prepare', 'run:npm_run_testHeadless']); + grunt.registerTask('test', [ + 'prepare', + 'run:npm_run_testHeadless', 'parallel' ]); - - grunt.registerTask('test-fast', [ - 'build', - 'testconfig', - 'fixture', - 'connect', - 'mocha' - ]); - - grunt.registerTask('translate', [ - 'pre-build', - 'validate', - 'concat:commons', - 'add-locale' - ]); - - grunt.registerTask('dev', [ - 'build', - 'testconfig', - 'fixture', - 'connect', - 'watch' - ]); + grunt.registerTask('ci-build', ['prepare', 'parallel']); }; diff --git a/README.md b/README.md index 6db04f1f25..2bbe914c96 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ Axe can be built using your local language. To do so, a localization file must b This will create a new build for axe, called `axe..js` and `axe..min.js`. If you want to build localized versions, simply pass in `--all-lang` instead. -To create a new translation for axe, start by running `grunt translate --lang=`. This will create a json file fin the `./locales` directory, with the default English text in it for you to translate. We welcome any localization for axe-core. For details on how to contribute, see the Contributing section below. +To create a new translation for axe, start by running `grunt translate --lang=`. This will create a json file fin the `./locales` directory, with the default English text in it for you to translate. We welcome any localization for axe-core. For details on how to contribute, see the Contributing section below. For details on the message syntax, see [Check Message Template](/docs/check-message-template.md). To update existing translation file, re-run `grunt translate --lang=`. This will add new messages used in English and remove messages which were not used in English. @@ -116,7 +116,7 @@ axe.configure({ 'aria-errormessage': { // Note: doT (https://github.com/olado/dot) templates are supported here. fail: - 'Der Wert der aria-errormessage {{~it.data:value}} `{{=value}}{{~}}` muss eine Technik verwenden, um die Message anzukündigen (z. B., aria-live, aria-describedby, role=alert, etc.).' + 'Der Wert der aria-errormessage ${data.values}` muss eine Technik verwenden, um die Message anzukündigen (z. B., aria-live, aria-describedby, role=alert, etc.).' } // ... } diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 0531970b94..0000000000 --- a/appveyor.yml +++ /dev/null @@ -1,29 +0,0 @@ -version: 1.0.{build}-{branch} - - # Test against this version of node. -environment: - nodejs_version: "10" -skip_tags: true - - # Install scripts. (runs after repo cloning) -install: - - ps: Install-Product node $env:nodejs_version - # Pin the version of iedriver used - - ps: choco install selenium-ie-driver --version 3.141.5 - - npm install - - # Post-install test scripts. -test_script: - # Include installed iedriver on path - - set PATH=C:\tools\selenium;%PATH% - - echo %PATH% - - node --version - - npm --version - - npm run build - # Run test scaffolding - - npx grunt testconfig fixture - - appveyor-retry npx grunt connect test-webdriver:ie - - npm run test:examples - - # Don't actually build. -build: off \ No newline at end of file diff --git a/axe.d.ts b/axe.d.ts index c4a4d49d7c..9fb543e4c6 100644 --- a/axe.d.ts +++ b/axe.d.ts @@ -41,7 +41,7 @@ declare namespace axe { values: TagValue[] | string[]; } interface RunOptions { - runOnly?: RunOnly; + runOnly?: RunOnly | TagValue[] | string[]; rules?: Object; iframes?: boolean; elementRef?: boolean; diff --git a/bower.json b/bower.json index a6ff446dd6..2e4176623f 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "axe-core", - "version": "3.4.1", + "version": "3.5.0", "contributors": [ { "name": "David Sturley", diff --git a/build/configure.js b/build/configure.js index a0e1fe09d5..f9df67f474 100644 --- a/build/configure.js +++ b/build/configure.js @@ -6,7 +6,8 @@ var clone = require('clone'); var dot = require('@deque/dot'); var templates = require('./templates'); var buildManual = require('./build-manual'); -var entities = new (require('html-entities')).AllHtmlEntities(); +var entities = new (require('html-entities').AllHtmlEntities)(); +var dotRegex = /\{\{.+?\}\}/g; var descriptionHeaders = '| Rule ID | Description | Impact | Tags | Enabled by default | Failures | Needs Review |\n| :------- | :------- | :------- | :------- | :------- | :------- | :------- |\n'; @@ -59,7 +60,10 @@ function buildRules(grunt, options, commons, callback) { Object.keys(result.messages).forEach(function(key) { // only convert to templated function for strings // objects handled later in publish-metadata.js - if (typeof result.messages[key] !== 'object') { + if ( + typeof result.messages[key] !== 'object' && + dotRegex.test(result.messages[key]) + ) { result.messages[key] = dot .template(result.messages[key]) .toString(); @@ -67,7 +71,7 @@ function buildRules(grunt, options, commons, callback) { }); } //TODO this is actually failureSummaries, property name should better reflect that - if (result.failureMessage) { + if (result.failureMessage && dotRegex.test(result.failureMessage)) { result.failureMessage = dot.template(result.failureMessage).toString(); } return result; @@ -86,7 +90,10 @@ function buildRules(grunt, options, commons, callback) { function getIncompleteMsg(summaries) { var result = {}; summaries.forEach(function(summary) { - if (summary.incompleteFallbackMessage) { + if ( + summary.incompleteFallbackMessage && + dotRegex.test(summary.incompleteFallbackMessage) + ) { result = dot.template(summary.incompleteFallbackMessage).toString(); } }); diff --git a/build/tasks/validate.js b/build/tasks/validate.js index 802c279f93..b8eeb987e3 100644 --- a/build/tasks/validate.js +++ b/build/tasks/validate.js @@ -37,8 +37,6 @@ function hasMultipleOutcomes(messages) { switch (key) { case 'pass': case 'fail': - return typeof messages[key] === 'string'; - case 'incomplete': return ['string', 'object'].includes(typeof messages[key]); diff --git a/build/test/config.js b/build/test/config.js index 8277347f6f..3bd16a3475 100644 --- a/build/test/config.js +++ b/build/test/config.js @@ -45,12 +45,7 @@ exports = module.exports = function(grunt, options) { [ 'test/integration/full/**/*.html', '!test/integration/full/**/frames/**/*.html' - ].concat([ - // These tests can be flaky on AppVeyor in Chrome and frequently fail - process.env.APPVEYOR - ? ['!test/integration/full/preload-cssom/preload-cssom.html'] - : [] - ]), + ], '<%= connect.test.options.port %>' ), run: true, diff --git a/build/test/get-test-urls.js b/build/test/get-test-urls.js new file mode 100644 index 0000000000..d267895db8 --- /dev/null +++ b/build/test/get-test-urls.js @@ -0,0 +1,38 @@ +const globby = require('globby'); + +const getTestUrls = async (host = `localhost`, port = `9876`) => { + const urls = [ + /** + * Unit tests -> Core + */ + `http://${host}:${port}/test/core/`, + /** + * Unit tests -> Checks + */ + `http://${host}:${port}/test/checks/`, + /** + * Unit tests -> Matches + */ + `http://${host}:${port}/test/rule-matches/`, + /** + * Unit tests -> Commons + */ + `http://${host}:${port}/test/commons/`, + /** + * Integration tests -> rules + */ + `http://${host}:${port}/test/integration/rules`, + /** + * Integration tests -> full + */ + ...( + await globby([ + 'test/integration/full/**/*.html', + '!test/integration/full/**/frames/**/*.html' + ]) + ).map(file => `http://${host}:${port}/${file}`) + ]; + return urls; +}; + +module.exports = getTestUrls; diff --git a/build/test/headless.js b/build/test/headless.js new file mode 100644 index 0000000000..76c90c01a3 --- /dev/null +++ b/build/test/headless.js @@ -0,0 +1,26 @@ +/** + * Note: + * For this to be run via `npm run test:headless` ensure server is running + */ +const getTestUrls = require('./get-test-urls'); +const { runner } = require('mocha-headless-chrome'); + +/** + * Run headless tests + */ +(async function runTests() { + const testUrls = await getTestUrls(); + for (const url of testUrls) { + const options = { + file: url + }; + const { result } = await runner(options); + + /** + * Stop test execution on failure, for early feedback + */ + if (result.stats.failures > 0) { + process.exit(1); + } + } +})(); diff --git a/doc/API.md b/doc/API.md index dd0e60ccf7..f8890512ec 100644 --- a/doc/API.md +++ b/doc/API.md @@ -475,6 +475,16 @@ axe.run( This example will only run the rules with the id of `ruleId1`, `ruleId2`, and `ruleId3`. No other rule will run. +Alternatively, runOnly can be passed an array of rules: + +```js +axe.run({ + runOnly: ['ruleId1', 'ruleId2', 'ruleId3']; +}, (err, results) => { + // ... +}) +``` + 3. Run all enabled Rules except for a list of rules The default operation for axe.run is to run all rules except for rules with the "experimental" tag. If certain rules should be disabled from being run, specify `options` as: @@ -575,6 +585,7 @@ The `assets` attribute expects an array of preload(able) constraints to be fetch | Asset Type | Description | | :--------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `cssom` | This asset type preloads all CSS Stylesheets rulesets specified in the page. The stylesheets can be an external cross-domain resource, a relative stylesheet or an inline style with in the head tag of the document. If the stylesheet is an external cross-domain a network request is made. An object representing the CSS Rules from each stylesheet is made available to the checks evaluate function as `preloadedAssets` at run-time | +| `media` | This asset type preloads metadata information of any HTMLMediaElement in the specified document | The `timeout` attribute in the object configuration is `optional` and has a fallback default value (10000ms). The `timeout` is essential for any network dependent assets that are preloaded, where-in if a given request takes longer than the specified/ default value, the operation is aborted. diff --git a/doc/aria-supported.md b/doc/aria-supported.md index 7698a5d233..9dd0462014 100644 --- a/doc/aria-supported.md +++ b/doc/aria-supported.md @@ -11,4 +11,3 @@ For a detailed description about how accessibility support is decided, see [How | aria-attribute | axe-core support | | ---------------- | ---------------- | | aria-describedat | No | -| aria-details | No | diff --git a/doc/check-message-template.md b/doc/check-message-template.md new file mode 100644 index 0000000000..b56408322d --- /dev/null +++ b/doc/check-message-template.md @@ -0,0 +1,124 @@ +# Check Message Template + +Axe-core uses a custom template to handle dynamic check messages (messages that use the `data` property to output values or to determine which message to display). The structure for the messages is as follows: + +## Simple Message + +A simple message is just a string that doesn't use the `data` property. Most checks uses this format. + +```json +{ + "messages": { + "pass": "Simple message for a passing check" + } +} +``` + +## Message with Data + +A message can also use the `data` property to output information from the check. If `data` is a String, Boolean, or Number, you can use the syntax `${data}` to have the message output the value of the `data` property. + +```js +// check.js +this.data(10); + +// check.json +{ + "messages": { + "pass": "Passed with a value of ${data}" + // => "Passed with a value of 10" + } +} +``` + +If `data` is an object, you can access properties of the object using the syntax `${data.propName}`. + +```js +// check.js +this.data({ + contrast: '3:1', + fontSize: '12px' +}); + +// check.json +{ + "messages": { + "fail": "Color-contrast failed with a contrast of ${data.contrast} and font size of ${data.fontSize}" + // => "Color-contrast failed with a contrast of 3:1 and font size of 12px" + } +} +``` + +## Singular and Plural Messages + +If the message needs to to know how many items are in the `data` property to determine the type of language to use (singular or plural), you can structure the message to use `singular` and `plural` properties. Use the syntax `${data.values}` to have the message output a comma-separated list of the items (`data.values` is provided by the template code for you). + +```js +// check.js +this.data(['item1', 'item2']); + +// check.json +{ + "messages": { + "fail": { + "singular": "Attribute ${data.values} is not allowed", + "plural": "Attributes: ${data.values} are not allowed" + } + // => Attributes: item1, item2 are not allowed + } +} +``` + +## Message Determined by Data + +Lastly, a message can use the `data` property to determine which message to display. Structure the message to use properties whose keys are the possible values of `data.messageKey`. You should also provide a `default` message that will be displayed if `messageKey` is not set. + +```js +// check.js +this.data({ + messageKey: 'imgNode' +}); + +// check.json +{ + "messages": { + "incomplete": { + "default": "Color-contrast could not be determined" + "bgImage": "Element's background color could not be determined due to a background image", + "imgNode": "Element's background color could not be determined because element contains an image node" + } + // => Element's background color could not be determined because element contains an image node + } +} +``` + +The messages can still use the syntax `${data.propName}` to access other properties on the `data` property. + +## Migrating From doT.js Template in Translations + +Axe-core use to use doT.js for it's temple library. To migrate from doT.js in a translation file, do the following: + +- If the message used `{{=it.data}}` or `{{=it.data.propName}}`, change the message to use the syntax `${data}` or `${data.propName}`. + +```diff +{ + "messages": { +- "incomplete": "Check that the