Skip to content

Commit

Permalink
feat(cli): add start of kayle cli
Browse files Browse the repository at this point in the history
  • Loading branch information
j-mendez committed Feb 18, 2024
1 parent c805027 commit ad14755
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 25 deletions.
63 changes: 38 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,31 +189,6 @@ type RunnerConfig = {
1. zh-CN ("Chinese-Simplified")
1. zh-TW ("Chinese-Traditional")

## Testing

For the comparison between using `fast_htmlcs`, `fast_axecore`, and the metrics for the 3rd party `@axe-core/playwright`.

1. `yarn build:test`

Checkout the [playwright-example](./kayle/tests/basic-playwright.spec.ts) or [puppeteer-example](./kayle/tests/basic.ts) for more information.

## Benchmarks

1. `fast_htmlcs` runs up to 110x base faster than HTML_CodeSniffer.
1. `fast_axecore` runs up to 2.5x - 15x base faster than the original axe by default and scales the larger the website.

Currently `fast_htmlcs` runs around 50x faster than axe-core and has several differences of handling the way issues are found. They both capture different cases and is best to used together which this library handles efficiently.

If you use [`@playwright/axe-core`](https://playwright.dev/docs/next/accessibility-testing) you can swap it out with the following [playwright-axe-example](./kayle/tests/basic-axe-playwright.spec.ts) and get an increase in issues found and major performance boost of at least 100%. You can also include multiple runners to extend the issues beyond the basics in folds.

## Performance Tips

As we set the foundation to mark test cases that can pass and increase our target on automating accessibility we have a couple of layers that can make a major difference to the project. The following will save drastic time and money if done.

1. Use a fast concurrent [crawler](https://github.com/a11ywatch/crawler) to gather all of the html to send to a web accessibility service that can perform audits like [pagemind](https://github.com/a11ywatch/pagemind) over CDP.

2. Use the pre-compiled browser extensions to avoid over the wire latency `yarn build:extension`.

## Browser Extension

If you want to compile a chrome extension for preloading scripts without needing to worry about bandwidth cost use the following to generate a custom extension to use.
Expand Down Expand Up @@ -315,6 +290,44 @@ const results = await kayle({
});
```

## CLI

The [kayle CLI](./kayle_cli/) is a work in progress.

```sh
npm install kayle_cli
```

Audit a website url.

```sh
kayle_cli https://www.somewebsite.com
```

## Testing

For the comparison between using `fast_htmlcs`, `fast_axecore`, and the metrics for the 3rd party `@axe-core/playwright`.

1. `yarn build:test`

Checkout the [playwright-example](./kayle/tests/basic-playwright.spec.ts) or [puppeteer-example](./kayle/tests/basic.ts) for more information.

## Benchmarks

1. `fast_htmlcs` runs up to 110x base faster than HTML_CodeSniffer.
1. `fast_axecore` runs up to 2.5x - 15x base faster than the original axe by default and scales the larger the website.

Currently `fast_htmlcs` runs around 50x faster than axe-core and has several differences of handling the way issues are found. They both capture different cases and is best to used together which this library handles efficiently.

If you use [`@playwright/axe-core`](https://playwright.dev/docs/next/accessibility-testing) you can swap it out with the following [playwright-axe-example](./kayle/tests/basic-axe-playwright.spec.ts) and get an increase in issues found and major performance boost of at least 100%. You can also include multiple runners to extend the issues beyond the basics in folds.

### Performance Tips

As we set the foundation to mark test cases that can pass and increase our target on automating accessibility we have a couple of layers that can make a major difference to the project. The following will save drastic time and money if done.

1. Use a fast concurrent [crawler](https://github.com/a11ywatch/crawler) to gather all of the html to send to a web accessibility service that can perform audits like [pagemind](https://github.com/a11ywatch/pagemind) over CDP.
2. Use the pre-compiled browser extensions to avoid over the wire latency `yarn build:extension`.

## Developing

In order to develop you need yarn v2 installed for the workspace.
Expand Down
4 changes: 4 additions & 0 deletions kayle_cli/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package.json
start.js
uninstall.js
pre-install.js
12 changes: 12 additions & 0 deletions kayle_cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "kayle_cli"
version = "0.0.1"
edition = "2021"
description = "The kayle CLI for web accessibility auditing"
repository = "https://github.com/a11ywatch/kayle"
categories = ["accessibility"]
authors = ["j-mendez"]
license = "MIT"

[dependencies]
clap = { version = "4.5.1", features = ["derive"]}
57 changes: 57 additions & 0 deletions kayle_cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# kayle_cli

The kayle CLI, for web accessibility audits. [WIP]

## Requirements

Node.js is required.
Install puppeteer globally `npm i puppeteer -g`.

## Installation

If Rust is installed.

```sh
cargo install kayle_cli
# or with node.
npm install kayle_cli
```

## Getting Started

Pass in a list of urls to get the results.

```sh
The kayle CLI for web accessibility auditing

Usage: kayle_cli [OPTIONS] <COMMAND>

Commands:
upgrade Upgrade kayle and the dependencies required
configure Configure the audits
help Print this message or the help of the given subcommand(s)

Options:
-s, --standard <STANDARD>
The accessibility standard to run, WCAG2A, WCAG2AA, WCAG2AAA, and Section508
--include-warnings <INCLUDE_WARNINGS>
Include warnings in the audit [possible values: true, false]
--include-notices <INCLUDE_NOTICES>
Include notices in the audit [possible values: true, false]
-r, --runners <RUNNERS>
The accessibility runner to use htmlcs, axecore, or kayle
-h, --help
Print help
-V, --version
Print version
```

```sh
kayle_cli https://www.drake.com
{"documentTitle":"Drake Industries | Custom, Durable, High-Quality Labels, Asset Tags and Custom Server Bezels","pageUrl":"https://www.drake.com/","issues":[{"context":"<h5 class=\"normal\">\n<div class=\"span12 widget-span ...</h5>","selector":"body>:nth-child(2)>:nth-child(1)>:nth-child(2)>:nth-child(1)>:nth-child(1)>:nth-child(2)>:nth-child(1)>:nth-child(1)>:nth-child(2)>:nth-child(1)>:nth-child(1)","code":"WCAG2AA.Principle1.Guideline1_3.1_3_1_A.G141","type":"error","typeCode":1,"message":"The heading structure is not logically nested. This h5 element should be an h2 to be properly nested.","runner":"htmlcs","recurrence":0},{"context":"<h5>Labels</h5>","selector":"#hs_cos_wrapper_module_1569856007055222>:nth-child(1)>:nth-child(2)>:nth-child(1)","code":"WCAG2AA.Principle1.Guideline1_3.1_3_1_A.G141","type":"error","typeCode":1,"message":"The heading structure is not logically nested. This h5 element should be an h3 to be properly nested.","runner":"htmlcs","recurrence":0},{"context":"<a href=\"https://www.drake.com/labels?hsLang=en\">Learn more</a>","selector":"#hs_cos_wrapper_module_1569856007055222>:nth-child(1)>:nth-child(3)>:nth-child(1)","code":"WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail","type":"error","typeCode":1,"message":"This element has insufficient contrast at this conformance level. Expected a contrast ratio of at least 4.5:1, but text in this element has a contrast ratio of 3.44:1. Recommendation: change text colour to #00171d.","runner":"htmlcs","recurrence":0},{"context":"<a href=\"https://www.drake.com/name-plates?hsLang=en\">Learn more</a>","selector":"#hs_cos_wrapper_module_1569856034269224>:nth-child(1)>:nth-child(3)>:nth-child(1)","code":"WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail","type":"error","typeCode":1,"message":"This element has insufficient contrast at this conformance level. Expected a contrast ratio of at least 4.5:1, but text in this element has a contrast ratio of 3.44:1. Recommendation: change text colour to #00171d.","runner":"htmlcs","recurrence":0},{"context":"<a href=\"https://www.drake.com/equipment-panel-overlays?hsLang=en\">Learn more</a>","selector":"#hs_cos_wrapper_module_1569856037305225>:nth-child(1)>:nth-child(3)>:nth-child(1)","code":"WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail","type":"error","typeCode":1,"message":"This element has insufficient contrast at this conformance level. Expected a contrast ratio of at least 4.5:1, but text in this element has a contrast ratio of 3.44:1. Recommendation: change text colour to #00171d.","runner":"htmlcs","recurrence":0},{"context":"<a href=\"https://www.drake.com/membrane-switches?hsLang=en\">Learn more</a>","selector":"#hs_cos_wrapper_module_1569856084644237>:nth-child(1)>:nth-child(3)>:nth-child(1)","code":"WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail","type":"error","typeCode":1,"message":"This element has insufficient contrast at this conformance level. Expected a contrast ratio of at least 4.5:1, but text in this element has a contrast ratio of 3.44:1. Recommendation: change text colour to #00171d.","runner":"htmlcs","recurrence":0},{"context":"<a href=\"https://www.drake.com/oem-bezel-re-branding?hsLang=en\">Learn more</a>","selector":"#hs_cos_wrapper_module_1569856082608235>:nth-child(1)>:nth-child(3)>:nth-child(1)","code":"WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail","type":"error","typeCode":1,"message":"This element has insufficient contrast at this conformance level. Expected a contrast ratio of at least 4.5:1, but text in this element has a contrast ratio of 3.44:1. Recommendation: change text colour to #00171d.","runner":"htmlcs","recurrence":0},{"context":"<a href=\"https://www.drake.com/safety?hsLang=en\">Learn more</a>","selector":"#hs_cos_wrapper_module_1569856080132233>:nth-child(1)>:nth-child(3)>:nth-child(1)","code":"WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail","type":"error","typeCode":1,"message":"This element has insufficient contrast at this conformance level. Expected a contrast ratio of at least 4.5:1, but text in this element has a contrast ratio of 3.44:1. Recommendation: change text colour to #00171d.","runner":"htmlcs","recurrence":0},{"context":"<a class=\"expandMenu\"><i></i><i></i><i></i></a>","selector":"#hs_cos_wrapper_module_14725592865174>:nth-child(1)","code":"WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.EmptyNoId","type":"error","typeCode":1,"message":"Anchor element found with no link content and no name and/or ID attribute.","runner":"htmlcs","recurrence":0}],"meta":{"errorCount":9,"warningCount":0,"noticeCount":0,"accessScore":100},"automateable":{"missingAltIndexs":[]}}%
```

## Todo

1. Configuration.
2. Allow Opt between puppeteer or playwright.
76 changes: 76 additions & 0 deletions kayle_cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use clap::{Parser, Subcommand};
use std::ffi::OsString;
use std::process::Command;
mod puppeteer_script;

#[derive(Debug, Subcommand)]
enum Commands {
/// Upgrade kayle and the dependencies required.
#[command(arg_required_else_help = true)]
Upgrade,
/// Configure the audits.
Configure,
/// The kayle program.
#[command(external_subcommand)]
Kayle(Vec<OsString>),
}

/// Web Accessibility Auditing using the kayle engine
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
/// The accessibility standard to run, WCAG2A, WCAG2AA, WCAG2AAA, and Section508.
#[arg(short, long)]
standard: Option<String>,
/// Include warnings in the audit.
#[arg(long)]
include_warnings: Option<bool>,
/// Include notices in the audit.
#[arg(long)]
include_notices: Option<bool>,
/// The accessibility runner to use htmlcs, axecore, or kayle.
#[arg(short, long)]
runners: Option<Vec<String>>,
#[command(subcommand)]
command: Commands,
}

fn main() {
let args = Args::parse();

match args.command {
Commands::Configure => {
println!("Configuration TODO");
}
Commands::Upgrade => {
Command::new("npm")
.args(["i", "kayle", "-g"])
.status()
.expect("Failed to execute command - npm install kayle command");
Command::new("npm")
.args(["i", "puppeteer", "-g"])
.status()
.expect("Failed to execute command - npm install puppeteer command");
}
Commands::Kayle(urls) => {
let accessibility_standard = args.standard.unwrap_or_default();
let include_warnings = args.include_warnings.unwrap_or_default();
let include_notices = args.include_notices.unwrap_or_default();
let runners = args.runners.unwrap_or_default().join(",");

for u in urls.iter() {
Command::new("node")
.args([
"-e",
puppeteer_script::SCRIPT_EXECUTION,
u.to_str().unwrap(),
&accessibility_standard,
if include_notices { "true"} else { "false" },
if include_warnings { "true"} else { "false" },
&runners])
.status()
.expect("Failed to execute node command. Make sure puppeteer and node is installed.");
}
}
}
}
32 changes: 32 additions & 0 deletions kayle_cli/src/puppeteer_script.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/// kayle script using puppeteer to drive the browser
pub const SCRIPT_EXECUTION: &'static str = r###"
const { argv, stdout } = require('node:process');
const puppeteer = require('puppeteer');
const { kayle, Standard } = require('kayle');
const args = argv.slice(1);
(async () => {
const browser = await puppeteer.launch({ headless: "new" });
const page = await browser.newPage();
if (process.env.LOG_ENABLED) {
page.on("console", (msg) => console.log(msg.text()));
}
const runners = args[4].split(",");
const audit = await kayle({
page,
browser,
runners: runners.length && runners[0] ? runners : ["htmlcs"],
includeWarnings: args[3] === "true",
includeNotices: args[2] === "true",
standard: args[1] || Standard.WCAG2AA,
origin: args[0],
});
stdout.write(JSON.stringify(audit));
process.exit();
})();
"###;

0 comments on commit ad14755

Please sign in to comment.