{"id":42186361,"url":"https://github.com/wallyax/wax-dev","last_synced_at":"2026-01-26T22:27:20.357Z","repository":{"id":239815249,"uuid":"800984816","full_name":"wallyax/wax-dev","owner":"wallyax","description":"A lightweight but extensive automated accessibiilty testing framework","archived":false,"fork":false,"pushed_at":"2025-04-25T13:22:01.000Z","size":56,"stargazers_count":1,"open_issues_count":1,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-26T17:19:10.699Z","etag":null,"topics":["accessibility","test","tools","web"],"latest_commit_sha":null,"homepage":"https://kb.wallyax.com/wax-dev","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wallyax.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"license.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-05-15T11:30:15.000Z","updated_at":"2025-04-28T13:56:09.000Z","dependencies_parsed_at":"2024-08-05T09:33:26.322Z","dependency_job_id":"e579f2ba-ed65-410c-81ba-c1f0ccc9b00a","html_url":"https://github.com/wallyax/wax-dev","commit_stats":null,"previous_names":["wallyax/wax-dev"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/wallyax/wax-dev","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wallyax%2Fwax-dev","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wallyax%2Fwax-dev/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wallyax%2Fwax-dev/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wallyax%2Fwax-dev/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wallyax","download_url":"https://codeload.github.com/wallyax/wax-dev/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wallyax%2Fwax-dev/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28789737,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T21:49:50.245Z","status":"ssl_error","status_checked_at":"2026-01-26T21:48:29.455Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accessibility","test","tools","web"],"created_at":"2026-01-26T22:27:18.680Z","updated_at":"2026-01-26T22:27:20.348Z","avatar_url":"https://github.com/wallyax.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WAX Dev Testing Framework\n\n## Description\nA lightweight and extensive automated accessibility testing framework\n\nAs a part of the WallyAX ecosystem accessibility tools, this package helps run accessibility tests on components and can easily be part of existing unit or integration testing.\n\n## Installation\n\nInstall the package using npm:\n\n```sh\nnpm install @wally-ax/wax-dev\n```\n\nOr using yarn:\n\n```sh\nyarn add @wally-ax/wax-dev\n```\n\n## Usage\n\n### Configuration\n\nCreate a configuration file named wax.config.js in the root directory of your project. The file should look like this:\n\n```javascript\nmodule.exports = {\nrules: [\"image-alt\", \"list\"],\napiKey:  \"YOUR_WALLY_DEVELOPER_API_KEY\"\n};\n```\n\nrules: An array of strings representing rule definitions. Available rules can be found [here](\"https://kb.wallyax.com/docs/wax-dev/rules\"). An empty array will include all rules.\n\napiKey: A string required for the wax-dev to work. You can get the api key from [WallyAX Account Portal](https://account.wallyax.com)\n\n  \n\n### Example Usage with Jest Testing Library in a React App\n\nrunWax function takes the rendered or pre-rendered html content and options as input.\n\nrunWaxUrl function takes the Website URL and options as input.  \n\nFor a ButtonList component:\n\n```javascript\nimport { render } from '@testing-library/react';\nimport ButtonList from './ButtonList';\nconst runWax = require('@wally-ax/wax-dev');\n\ndescribe('ButtonList AX Test', () =\u003e {\n  test('should have no accessibility violations', async () =\u003e {\n    const { container } = render(\u003cButtonList /\u003e);\n    const ele = JSON.stringify(container.innerHTML);\n    const violations = await runWax(ele, { rules: [\"images-alt\"] });\n    expect(violations).toHaveLength(0);\n  });\n});\n```\n\nNote: the rule configuration at test level will be overridden by the global configuration in wax.config.js\n\n### Results\n\nThe results will be an array of violations based on the config. Example:\n\n```json\n[\n  {\n    \"description\": \"Ensures \u003cimg\u003e elements have alternate text or a role of none or presentation\",\n    \"element\": \"\u003cimg src=\\\"logo\\\"\u003e\",\n    \"impact\": \"critical\",\n    \"message\": \"Images must have alternate text\"\n  },\n  {\n    \"description\": \"Ensures every form element has a label\",\n    \"element\": \"\u003cinput type=\\\"text\\\"\u003e\",\n    \"impact\": \"critical\",\n    \"message\": \"Form elements must have labels\"\n  },\n  {\n    \"description\": \"Ensures that lists are structured correctly\",\n    \"element\": \"\u003cul\u003e\u003cp\u003eList item 2\u003c/p\u003e\u003cli\u003eList item ...\u003c/ul\u003e\",\n    \"impact\": \"serious\",\n    \"message\": \"\u003cul\u003e and \u003col\u003e must only directly contain \u003cli\u003e, \u003cscript\u003e or \u003ctemplate\u003e elements\"\n  }\n]\n\n```\n\n### Example Usage with Cypress Testing Library in a React App\n\nFor a Button component:\n\nButton.cy.js\n\n```javascript\nimport runWax from '@wally-ax/wax-dev';\nimport waxConfig from './waxconfig';\n\nlet violations;\n\ndescribe('Button Component Tests', () =\u003e {\n  it('should have no accessibility violations', () =\u003e {\n    cy.mount(\u003cButton variant=\"ghost\" size=\"large\"\u003eOutline\u003c/Button\u003e);\n    cy.get('body').then(async ($body) =\u003e {\n      const ele = $body.html();\n      violations = await runWax(ele, waxConfig);\n      expect(violations).to.have.lengthOf(0);\n    });\n  });\n  \n  it('write_file', () =\u003e {\n    cy.writeFile('src/components/ui/tests/button_violation.json', violations);\n  });\n});\n```\n\nCreate a waxConfig.js file:\n\n```javascript\nconst waxConfig = {\n  rules: [],\n  apiKey: \"API KEY\"\n};\n\nexport default waxConfig;\n\n```\n\n### Results\n\nThe results will be an array of violations based on the config. A **button_violation.json** file will be created and violations will be saved.\n\n## Example usage for running URL audit\n\n```javascript\nimport { runWaxUrl } from '@wally-ax/wax-dev';\nimport waxConfig from './waxconfig';\n\nasync function performWaxOperation(url, waxConfig) {\n    try {\n        const resultUrl = await runWaxUrl(url, waxConfig);\n        console.log('resultUrl', resultUrl);\n    } catch (error) {\n        console.error('Error running Wax URL:', error);\n    }\n}\nconst url = 'http://example.com'; // Replace with your actual URL\n\nperformWaxOperation(url, waxConfig);\n\n```\n\n## Integrate Storybook with WAX Dev\n\nCreate a folder inside the **.storybook** folder.\n\nInside that folder, create a **register.js** and **panel.js** file.\n\n####  register.js\n\n```javascript\n// .storybook/my-addon/register.js - location\nimport React from 'react';\nimport { addons, types } from '@storybook/addons';\nimport MyPanel from './panel';\n\nconst ADDON_ID = 'my-addon';\nconst PANEL_ID = `${ADDON_ID}/panel`;\n\naddons.register(ADDON_ID, () =\u003e {\n  addons.add(PANEL_ID, {\n    type: types.PANEL,\n    title: 'WAX Accessibility Issues',\n    render: ({ active, key }) =\u003e \u003cMyPanel active={active} key={key} /\u003e,\n  });\n});\n```\n#### panel.js\n\n```javascript\nimport React, { useEffect, useState } from 'react';\nimport { AddonPanel } from '@storybook/components';\nimport { useParameter } from '@storybook/api';\nimport { addons } from '@storybook/addons';\nimport Icon from '@mdi/react';\nimport { mdiChevronRight } from '@mdi/js';\n\nconst ADDON_ID = 'my-addon';\nconst PANEL_ID = `${ADDON_ID}/panel`;\n\nconst MyPanel = ({ active }) =\u003e {\n  const [violations, setViolations] = useState([]);\n  const value = useParameter('myAddonParameter', 'Default information');\n  const fetchDataPath = useParameter('fetchDataPath', null);\n\n  useEffect(() =\u003e {\n    if (fetchDataPath) {\n      const fetchData = async () =\u003e {\n        const response = await fetch(fetchDataPath);\n        const result = await response.json();\n        setViolations(result);\n      };\n      fetchData();\n    }\n  }, [fetchDataPath]);\n\n  const groupedViolations = violations.reduce((acc, violation) =\u003e {\n    const { description } = violation;\n    if (!acc[description]) {\n      acc[description] = [];\n    }\n    acc[description].push(violation);\n    return acc;\n  }, {});\n\n  return (\n    \u003cAddonPanel active={active}\u003e\n      \u003cdiv style={{ padding: '10px' }}\u003e\n        {Object.keys(groupedViolations)?.length \u003e 0 ? (\n          Object.keys(groupedViolations).map((description, index) =\u003e (\n            \u003cdiv key={index} style={{ marginBottom: '10px', border: '1px solid #ccc', borderRadius: '4px' }}\u003e\n              \u003cbutton\n                onClick={() =\u003e {\n                  const content = document.getElementById(`group-${index}-content`);\n                  if (content.style.display === 'none') {\n                    content.style.display = 'block';\n                  } else {\n                    content.style.display = 'none';\n                  }\n                }}\n                style={{\n                  display: 'flex',\n                  alignItems: 'center',\n                  width: '100%',\n                  border: 'none',\n                  padding: '10px',\n                  textAlign: 'left',\n                  cursor: 'pointer',\n                  fontWeight: 'bold',\n                }}\n              \u003e\n                \u003cIcon path={mdiChevronRight} size={1} /\u003e\n                {description}\n              \u003c/button\u003e\n              \u003cdiv id={`group-${index}-content`} style={{ display: 'none', padding: '10px' }}\u003e\n                {groupedViolations[description].map((violation, idx) =\u003e (\n                  \u003cdiv key={idx} style={{ marginBottom: '10px' }}\u003e\n                    \u003cp style={{ margin: '0 0 10px' }}\u003e\n                      \u003cspan style={{ fontWeight: 'bold', fontSize: '16px' }}\u003eViolation {idx + 1}:\u003c/span\u003e\n                    \u003c/p\u003e\n                    \u003cp style={{ margin: '0 0 10px' }}\u003e\n                      \u003cspan style={{ color: '#fff', backgroundColor: '#ff4400', borderRadius: '9999px', padding: '2px 6px' }}\u003e\n                        {violation.severity}\n                      \u003c/span\u003e\n                    \u003c/p\u003e\n                    \u003cp style={{ margin: '0 0 10px', fontSize: '14px' }}\u003e\n                      \u003cspan style={{ fontWeight: 'bold' }}\u003eMessage:\u003c/span\u003e {violation.message}\n                    \u003c/p\u003e\n                    \u003cpre style={{ whiteSpace: 'pre-wrap', wordWrap: 'break-word' }}\u003e\n                      {violation.element}\n                    \u003c/pre\u003e\n                  \u003c/div\u003e\n                ))}\n              \u003c/div\u003e\n            \u003c/div\u003e\n          ))\n        ) : (\n          \u003cp style={{ textAlign: 'center', fontSize: '16px', fontWeight: 'bold' }}\u003e\n            No accessibility violations found.\n          \u003c/p\u003e\n        )}\n      \u003c/div\u003e\n    \u003c/AddonPanel\u003e\n  );\n};\n\nexport default MyPanel;\n```\n\nAdd parameters in the stories with the respective test result file name. For example, for the **Button component**:\n\n```sh\nparameters: {\n  myAddonParameter: 'This is constant information for the Button component.',\n  fetchDataPath: 'src/components/ui/tests/button_violation.json'\n}\n```\n\n**Button.stories.jsx**\n\n```javascript\nimport React from 'react';\nimport { Button } from '@/components/ui/button';\n\nexport default {\n  title: 'Components/Button',\n  component: Button,\n  argTypes: {\n    asChild: {\n      control: 'boolean',\n    },\n  },\n  parameters: {\n    myAddonParameter: 'This is constant information for the Button component.',\n    fetchDataPath: 'src/components/ui/tests/button_violation.json'\n  },\n};\n\nconst Template = (args) =\u003e \u003cButton {...args}\u003eButton\u003c/Button\u003e;\n\nexport const Default = Template.bind({});\nDefault.args = {\n  variant: 'default',\n  size: 'medium',\n};\n```\n\nNote: Run the test before starting the Storybook.\n\n#### You will see the new panel named \"Wax-Dev\" with violations in storybook.\n\n## License\n\nMozilla Public License Version 2.0 (see license.txt)\n\nWAX Dev is licensed as Mozilla Public License Version 2.0 and the copyright is owned by Wally Solutions Pvt Ltd and Contributors.\n\nBy contributing to WAX Dev, you agree that your contributions will be licensed under its Mozilla Public License Version 2.0.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwallyax%2Fwax-dev","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwallyax%2Fwax-dev","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwallyax%2Fwax-dev/lists"}