axe-cdp.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. const CDP = require('chrome-remote-interface');
  2. const axeCore = require('axe-core');
  3. const assert = require('assert');
  4. const { parse: parseURL } = require('url');
  5. // Cheap URL validation
  6. const isValidURL = input => {
  7. const u = parseURL(input);
  8. return u.protocol && u.host;
  9. };
  10. const example = async url => {
  11. // eslint-disable-next-line new-cap
  12. const client = await CDP();
  13. const { Runtime: runtime, Page: page } = client;
  14. let results;
  15. try {
  16. await page.enable();
  17. await runtime.enable();
  18. await page.navigate({ url });
  19. // This function is injected into the browser and is responsible for
  20. // running `axe-core`.
  21. const browserCode = () => {
  22. /* eslint-env browser */
  23. return new Promise((resolve, reject) => {
  24. const axe = window.axe;
  25. if (!axe) {
  26. throw new Error('Unable to find axe-core');
  27. }
  28. // Finally, run axe-core
  29. axe
  30. .run()
  31. // For some reason, when resolving with an object, CDP ignores
  32. // its value (`results.result.value` is undefined). By
  33. // `JSON.stringify()`ing it, we can `JSON.parse()` it later on
  34. // and return a valid results set.
  35. .then(results => JSON.stringify(results))
  36. .then(resolve)
  37. .catch(reject);
  38. });
  39. };
  40. // Inject axe-core
  41. await runtime.evaluate({
  42. expression: axeCore.source
  43. });
  44. // Run axe-core
  45. const ret = await runtime.evaluate({
  46. expression: `(${browserCode})()`,
  47. awaitPromise: true
  48. });
  49. // re-parse
  50. results = JSON.parse(ret.result.value);
  51. } catch (err) {
  52. // Ensure we close the client before exiting the fn
  53. client.close();
  54. throw err;
  55. }
  56. client.close();
  57. return results;
  58. };
  59. // node axe-cdp.js <url>
  60. const url = process.argv[2];
  61. assert(isValidURL(url), 'Invalid URL');
  62. example(url)
  63. .then(results => {
  64. console.log(results);
  65. })
  66. .catch(err => {
  67. console.error('Error running axe-core:', err.message);
  68. process.exit(1);
  69. });