├── .github
├── CODEOWNERS
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── feature_request.md
│ └── general_question.md
├── dependabot.yml
├── policies
│ └── resourceManagement.yml
└── pull_request_template.md
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── csharp-selenium-webdriver-sample
├── .gitignore
├── CSharpSeleniumWebdriverSample.csproj
├── README.md
├── Resources
│ ├── screenshot-dotnet-test-failure.png
│ ├── screenshot-dotnet-test-success.png
│ ├── screenshot-logs-tab.png
│ └── screenshot-tests-tab.png
├── SamplePage.html
├── SamplePageTests.cs
├── WebDriverFactory.cs
└── azure-pipelines.yml
├── typescript-playwright-sample
├── .gitignore
├── README.md
├── assets
│ ├── screenshot-failing-logs-tab.png
│ ├── screenshot-failing-scans-tab.png
│ ├── screenshot-failing-tests-tab.png
│ ├── screenshot-local-yarn-test.png
│ ├── screenshot-passing-logs-tab.png
│ ├── screenshot-passing-scans-tab.png
│ └── screenshot-passing-tests-tab.png
├── azure-pipelines.yml
├── package.json
├── playwright.config.ts
├── src
│ └── index.html
├── tests
│ ├── export-to-sarif.ts
│ ├── failing-examples.spec.ts
│ └── passing-examples.spec.ts
└── yarn.lock
├── typescript-selenium-webdriver-sample
├── .gitignore
├── .vscode
│ └── launch.json
├── README.md
├── assets
│ ├── screenshot-logs-tab.png
│ ├── screenshot-scans-tab.png
│ ├── screenshot-tests-tab.png
│ └── screenshot-yarn-test-success.png
├── azure-pipelines.yml
├── jest.config.js
├── package.json
├── src
│ └── index.html
├── tests
│ ├── __snapshots__
│ │ └── index.test.ts.snap
│ ├── index.test.ts
│ └── webdriver-factory.ts
├── tsconfig.json
└── yarn.lock
└── windows-app-resources
└── README.md
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # default owners for everything in the repository.
2 | * @microsoft/accessibility-insights-code-owners
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug, needs triage
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Describe the bug
11 |
12 |
13 |
14 | **To Reproduce**
15 | Steps to reproduce the behavior:
16 |
17 | 1. Go to '...'
18 | 2. Run '...'
19 | 3. See error
20 |
21 | ## Expected behavior
22 |
23 |
24 |
25 | ## Extension (please complete the following information)
26 |
27 | - OS [e.g. Windows/Mac]:
28 | - OS Version [e.g. 1.140.1]:
29 | - Node Version [e.g. 10.15.3]:
30 |
31 | ## Are you willing to submit a PR?
32 |
33 |
34 |
35 | ## Did you search for similar existing issues?
36 |
37 |
38 |
39 | ## Additional context
40 |
41 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: feature request
6 | assignees: ''
7 | ---
8 |
9 | ## Is your feature request related to a problem? Please describe.
10 |
11 |
12 | ## Describe the desired outcome
13 |
14 |
15 | ## Describe alternatives you've considered
16 |
17 |
18 | ## Additional context
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/general_question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: General Question
3 | about: This is a template for people to ask questions that don't fit into any other issue categories
4 | title: ''
5 | labels: question
6 | assignees: ''
7 | ---
8 |
9 | ## Your question here
10 |
11 |
15 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: nuget
4 | directory: "/csharp-selenium-webdriver-sample"
5 | schedule:
6 | interval: daily
7 | time: "08:30" # UTC
8 | open-pull-requests-limit: 10 # Default value of 5 has been problematic
9 | - package-ecosystem: npm
10 | directory: "/typescript-selenium-webdriver-sample"
11 | schedule:
12 | interval: daily
13 | time: "08:30" # UTC
14 | versioning-strategy: increase
15 | ignore:
16 | # Major version of @types/node is pinned to match the version of node we
17 | # use for builds (ideally, latest LTS)
18 | - dependency-name: "@types/node"
19 | versions:
20 | - ">=17.0.0"
21 | open-pull-requests-limit: 10 # Default value of 5 has been problematic
22 | - package-ecosystem: npm
23 | directory: "/typescript-playwright-sample"
24 | schedule:
25 | interval: daily
26 | time: "08:30" # UTC
27 | versioning-strategy: increase
28 | ignore:
29 | # Major version of @types/node is pinned to match the version of node we
30 | # use for builds (ideally, latest LTS)
31 | - dependency-name: "@types/node"
32 | versions:
33 | - ">=21.0.0"
34 | open-pull-requests-limit: 10 # Default value of 5 has been problematic
35 |
--------------------------------------------------------------------------------
/.github/policies/resourceManagement.yml:
--------------------------------------------------------------------------------
1 | id:
2 | name: GitOps.PullRequestIssueManagement
3 | description: GitOps.PullRequestIssueManagement primitive
4 | owner:
5 | resource: repository
6 | disabled: false
7 | where:
8 | configuration:
9 | resourceManagementConfiguration:
10 | scheduledSearches:
11 | - description:
12 | frequencies:
13 | - hourly:
14 | hour: 3
15 | filters:
16 | - isOpen
17 | - isIssue
18 | - noActivitySince:
19 | days: 4
20 | - isNotLabeledWith:
21 | label: 'status: no recent activity'
22 | - hasLabel:
23 | label: 'status: needs author feedback'
24 | actions:
25 | - addLabel:
26 | label: 'status: no recent activity'
27 | - addReply:
28 | reply: This issue has been automatically marked as stale because it is marked as requiring author feedback but has not had any activity for **4 days**. It will be closed if no further activity occurs **within 3 days of this comment**. Thank you for contributing to Accessibility Insights!
29 | - description:
30 | frequencies:
31 | - hourly:
32 | hour: 3
33 | filters:
34 | - isOpen
35 | - isIssue
36 | - hasLabel:
37 | label: 'status: no recent activity'
38 | - noActivitySince:
39 | days: 3
40 | actions:
41 | - closeIssue
42 | eventResponderTasks:
43 | - if:
44 | - payloadType: Pull_Request
45 | - hasLabel:
46 | label: 'pr: auto-merge'
47 | then:
48 | - enableAutoMerge:
49 | mergeMethod: Squash
50 | description:
51 | - if:
52 | - payloadType: Pull_Request
53 | - labelRemoved:
54 | label: 'pr: auto-merge'
55 | then:
56 | - disableAutoMerge
57 | description:
58 | - if:
59 | - payloadType: Issues
60 | - or:
61 | - isAction:
62 | action: Opened
63 | - isAction:
64 | action: Reopened
65 | - not:
66 | hasLabel:
67 | label: task
68 | - not: isAssignedToSomeone
69 | then:
70 | - addLabel:
71 | label: 'status: new'
72 | - assignIcmUsers:
73 | teamId: 57436
74 | primary: True
75 | secondary: False
76 | description:
77 | - if:
78 | - payloadType: Issues
79 | - isAction:
80 | action: Opened
81 | - hasLabel:
82 | label: task
83 | then:
84 | - addLabel:
85 | label: 'status: new'
86 | description:
87 | - if:
88 | - payloadType: Issues
89 | - labelAdded:
90 | label: 'status: needs author feedback'
91 | then:
92 | - removeLabel:
93 | label: 'status: new'
94 | - addReply:
95 | reply: The team requires additional author feedback; please review their replies and update this issue accordingly. Thank you for contributing to Accessibility Insights!
96 | description:
97 | - if:
98 | - payloadType: Issues
99 | - isActivitySender:
100 | issueAuthor: True
101 | - hasLabel:
102 | label: 'status: needs author feedback'
103 | - not:
104 | isAction:
105 | action: Closed
106 | then:
107 | - addLabel:
108 | label: 'status: needs attention'
109 | - removeLabel:
110 | label: 'status: needs author feedback'
111 | description:
112 | - if:
113 | - payloadType: Issues
114 | - labelAdded:
115 | label: 'status: ready for triage'
116 | then:
117 | - assignTo:
118 | users:
119 | - nang4ally
120 | - addReply:
121 | reply: This issue has been marked as ready for team triage; we will triage it in our weekly review and update the issue. Thank you for contributing to Accessibility Insights!
122 | description:
123 | - if:
124 | - payloadType: Issues
125 | - labelAdded:
126 | label: 'status: needs investigation'
127 | then:
128 | - addReply:
129 | reply: 'This issue requires additional investigation by the Accessibility Insights team. When the issue is ready to be triaged again, we will update the issue with the investigation result and add "status: ready for triage". Thank you for contributing to Accessibility Insights!'
130 | - removeLabel:
131 | label: 'status: ready for triage'
132 | description:
133 | - if:
134 | - payloadType: Issues
135 | - labelAdded:
136 | label: good first issue
137 | then:
138 | - addLabel:
139 | label: help wanted
140 | description:
141 | - if:
142 | - payloadType: Issues
143 | - labelAdded:
144 | label: 'resolution: out of scope'
145 | then:
146 | - addReply:
147 | reply: 'This issue has been marked as being beyond the support scope of Accessibility Insights. It will now be closed automatically for house-keeping purposes. '
148 | - closeIssue
149 | description:
150 | - if:
151 | - payloadType: Issues
152 | - or:
153 | - labelAdded:
154 | label: 'status: needs author feedback'
155 | - labelAdded:
156 | label: 'status: needs attention'
157 | - labelAdded:
158 | label: 'status: needs investigation'
159 | - labelAdded:
160 | label: 'status: blocked'
161 | - labelAdded:
162 | label: 'status: ready for triage'
163 | - labelAdded:
164 | label: 'status: ready for work'
165 | - labelAdded:
166 | label: 'status: active'
167 | - labelAdded:
168 | label: 'status: resolved'
169 | - labelAdded:
170 | label: 'resolution: out of scope'
171 | then:
172 | - removeLabel:
173 | label: 'status: new'
174 | description:
175 | - if:
176 | - payloadType: Issues
177 | - or:
178 | - labelAdded:
179 | label: 'status: new'
180 | - labelAdded:
181 | label: 'status: needs attention'
182 | - labelAdded:
183 | label: 'status: needs investigation'
184 | - labelAdded:
185 | label: 'status: blocked'
186 | - labelAdded:
187 | label: 'status: ready for triage'
188 | - labelAdded:
189 | label: 'status: ready for work'
190 | - labelAdded:
191 | label: 'status: active'
192 | - labelAdded:
193 | label: 'status: resolved'
194 | - labelAdded:
195 | label: 'resolution: out of scope'
196 | then:
197 | - removeLabel:
198 | label: 'status: needs author feedback'
199 | description:
200 | - if:
201 | - payloadType: Issues
202 | - or:
203 | - labelAdded:
204 | label: 'status: new'
205 | - labelAdded:
206 | label: 'status: needs author feedback'
207 | - labelAdded:
208 | label: 'status: needs investigation'
209 | - labelAdded:
210 | label: 'status: blocked'
211 | - labelAdded:
212 | label: 'status: ready for triage'
213 | - labelAdded:
214 | label: 'status: ready for work'
215 | - labelAdded:
216 | label: 'status: active'
217 | - labelAdded:
218 | label: 'status: resolved'
219 | - labelAdded:
220 | label: 'resolution: out of scope'
221 | then:
222 | - removeLabel:
223 | label: 'status: needs attention'
224 | description:
225 | - if:
226 | - payloadType: Issues
227 | - or:
228 | - labelAdded:
229 | label: 'status: new'
230 | - labelAdded:
231 | label: 'status: needs author feedback'
232 | - labelAdded:
233 | label: 'status: needs attention'
234 | - labelAdded:
235 | label: 'status: blocked'
236 | - labelAdded:
237 | label: 'status: ready for triage'
238 | - labelAdded:
239 | label: 'status: ready for work'
240 | - labelAdded:
241 | label: 'status: active'
242 | - labelAdded:
243 | label: 'status: resolved'
244 | - labelAdded:
245 | label: 'resolution: out of scope'
246 | then:
247 | - removeLabel:
248 | label: 'status: needs investigation'
249 | description:
250 | - if:
251 | - payloadType: Issues
252 | - or:
253 | - labelAdded:
254 | label: 'status: new'
255 | - labelAdded:
256 | label: 'status: needs author feedback'
257 | - labelAdded:
258 | label: 'status: needs attention'
259 | - labelAdded:
260 | label: 'status: needs investigation'
261 | - labelAdded:
262 | label: 'status: ready for triage'
263 | - labelAdded:
264 | label: 'status: ready for work'
265 | - labelAdded:
266 | label: 'status: active'
267 | - labelAdded:
268 | label: 'status: resolved'
269 | - labelAdded:
270 | label: 'resolution: out of scope'
271 | then:
272 | - removeLabel:
273 | label: 'status: blocked'
274 | description:
275 | - if:
276 | - payloadType: Issues
277 | - or:
278 | - labelAdded:
279 | label: 'status: new'
280 | - labelAdded:
281 | label: 'status: needs author feedback'
282 | - labelAdded:
283 | label: 'status: needs attention'
284 | - labelAdded:
285 | label: 'status: needs investigation'
286 | - labelAdded:
287 | label: 'status: blocked'
288 | - labelAdded:
289 | label: 'status: ready for work'
290 | - labelAdded:
291 | label: 'status: active'
292 | - labelAdded:
293 | label: 'status: resolved'
294 | - labelAdded:
295 | label: 'resolution: out of scope'
296 | then:
297 | - removeLabel:
298 | label: 'status: ready for triage'
299 | description:
300 | - if:
301 | - payloadType: Issues
302 | - or:
303 | - labelAdded:
304 | label: 'status: new'
305 | - labelAdded:
306 | label: 'status: needs author feedback'
307 | - labelAdded:
308 | label: 'status: needs attention'
309 | - labelAdded:
310 | label: 'status: needs investigation'
311 | - labelAdded:
312 | label: 'status: blocked'
313 | - labelAdded:
314 | label: 'status: ready for triage'
315 | - labelAdded:
316 | label: 'status: active'
317 | - labelAdded:
318 | label: 'status: resolved'
319 | - labelAdded:
320 | label: 'resolution: out of scope'
321 | then:
322 | - removeLabel:
323 | label: 'status: ready for work'
324 | description:
325 | - if:
326 | - payloadType: Issues
327 | - hasLabel:
328 | label: task
329 | - isAction:
330 | action: Closed
331 | then:
332 | - addLabel:
333 | label: 'status: resolved'
334 | - removeLabel:
335 | label: 'status: active'
336 | - removeLabel:
337 | label: 'status: new'
338 | description:
339 | - if:
340 | - payloadType: Issues
341 | - or:
342 | - labelAdded:
343 | label: 'status: new'
344 | - labelAdded:
345 | label: 'status: needs author feedback'
346 | - labelAdded:
347 | label: 'status: needs attention'
348 | - labelAdded:
349 | label: 'status: needs investigation'
350 | - labelAdded:
351 | label: 'status: blocked'
352 | - labelAdded:
353 | label: 'status: ready for triage'
354 | - labelAdded:
355 | label: 'status: ready for work'
356 | - labelAdded:
357 | label: 'status: resolved'
358 | - labelAdded:
359 | label: 'resolution: out of scope'
360 | then:
361 | - removeLabel:
362 | label: 'status: active'
363 | description:
364 | - if:
365 | - payloadType: Issues
366 | - or:
367 | - labelAdded:
368 | label: 'status: new'
369 | - labelAdded:
370 | label: 'status: needs author feedback'
371 | - labelAdded:
372 | label: 'status: needs attention'
373 | - labelAdded:
374 | label: 'status: needs investigation'
375 | - labelAdded:
376 | label: 'status: blocked'
377 | - labelAdded:
378 | label: 'status: ready for triage'
379 | - labelAdded:
380 | label: 'status: ready for work'
381 | - labelAdded:
382 | label: 'status: active'
383 | - labelAdded:
384 | label: 'resolution: out of scope'
385 | then:
386 | - removeLabel:
387 | label: 'status: resolved'
388 | description:
389 | - if:
390 | - payloadType: Issue_Comment
391 | - isActivitySender:
392 | issueAuthor: True
393 | - hasLabel:
394 | label: 'status: needs author feedback'
395 | then:
396 | - addLabel:
397 | label: 'status: needs attention'
398 | - removeLabel:
399 | label: 'status: needs author feedback'
400 | description:
401 | onFailure:
402 | onSuccess:
403 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | #### Details
2 |
3 |
4 |
5 | ##### Motivation
6 |
7 |
8 |
9 | ##### Context
10 |
11 |
12 |
13 |
14 |
15 | #### Pull request checklist
16 |
17 |
18 | - [ ] If this PR addresses an existing issue, it is linked: Fixes #0000
19 | - [ ] New sample content is commented at a similar verbosity as existing content
20 | - [ ] All updated/modified sample code builds and runs in at least one PR/CI build
21 | - [ ] PR checks for builds named `[failing example] ...` pass in the PR build, then confirm they fail in the CI build
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | This project welcomes contributions and suggestions.
4 |
5 | For larger contributions (eg, a new sample), we recommend starting out by filing an issue (use the "Suggestion" template) to discuss your idea with us first.
6 |
7 | For small contributions (eg, a minor fix to an existing sample), feel free to just send a Pull Request.
8 |
9 | ## Pull Requests
10 |
11 | Before sending a pull request, please double check that:
12 |
13 | * Any new sample content being added is documented with a sample-level README.md and verbosely commented inline.
14 | * The tests run and pass in each sample you're modifying.
15 |
16 | Pull requests will be reviewed and merged by a member of the Accessibility Insights team.
17 |
18 | ## Contributor License Agreement
19 |
20 | Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
21 |
22 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
23 |
24 | ## Code of Conduct
25 |
26 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Axe + Azure Pipelines: Automate accessibility testing in your CI builds
2 |
3 | Watch a [short intro video](https://www.youtube.com/watch?v=SarmnCULt8M) to get started with automated accessibility tests in Azure pipelines. Please note that these samples are applicable to web projects that have UI automation tests. Benefits include,
4 |
5 | - Automated accessibility tests run during Continuous Integration and Pull Request builds, ensuring that all code changes are free of common easily-detected accessibility issues before they go to production
6 | - Builds can be configured to fail based on the results of the automated accessibility tests, preventing both new accessibility bugs and regressions
7 | - Failure details and _how to fix_ information can be viewed in Azure DevOps under Builds, making it quick and easy to investigate and resolve the accessibility issues
8 |
9 | This repository contains sample projects (see next section [Available samples](#available-samples)) demonstrating how to implement automated accessibility testing in [Azure Pipelines](https://azure.microsoft.com/en-us/services/devops/pipelines/) builds using [axe-core](https://github.com/dequelabs/axe-core), the same accessibility scanning engine used in [Accessibility Insights for Web](https://accessibilityinsights.io/docs/en/web/overview), and [Axe.Windows](https://github.com/microsoft/axe-windows), the same accessibility scanning engine used in [Accessibility Insights for Windows](https://accessibilityinsights.io/docs/en/windows/overview/).
10 |
11 | ## Available samples
12 |
13 | The following sample projects specify the main technologies used. A team that uses comparable tools and frameworks should be able to refer to the sample and update their existing tests to incorporate automated accessibility checks.
14 |
15 | - **[Sample 1: typescript-playwright-sample](./typescript-playwright-sample)**:
16 |
17 | - Useful for teams using Playwright and TypeScript/JavaScript.
18 |
19 | - **[Sample 2: typescript-selenium-webdriver-sample](./typescript-selenium-webdriver-sample)**:
20 |
21 | - Useful for teams using Selenium and TypeScript/JavaScript.
22 |
23 | - **[Sample 3: CSharpSeleniumWebdriverSample](./csharp-selenium-webdriver-sample)**:
24 |
25 | - Useful for teams using Selenium and C#.
26 |
27 | ## Other Resources
28 |
29 | The following may be helpful as an example of how our accessibility scanning tools have been used where the product is not based on HTML:
30 |
31 | - **[WindowsAppResources](./windows-app-resources)**:
32 |
33 | - Useful for teams developing non-browser-based Windows applications. These applications can use any language or framework.
34 |
35 | ## Requests
36 |
37 | _Are we missing a sample or resource you'd like to see? [File a sample request](https://github.com/microsoft/axe-pipelines-samples/issues/new?assignees=&labels=sample_request&template=feature_request.md&title=Sample+Request%3A+%3Csample+name+here%3E) or [submit a pull request](./CONTRIBUTING.md)!_
38 |
39 | ## Disclaimer
40 |
41 | Automated accessibility tests can detect some common accessibility problems such as missing or invalid properties. But most accessibility problems can only be discovered through manual testing. We recommend **both** automated testing, to continuously protect against simple types of issues, and regular manual assessments with [Accessibility Insights for Web](https://accessibilityinsights.io/docs/en/web/overview), a free and open source dev tool that walks you through assessing a website for [WCAG 2.1 AA](https://www.w3.org/WAI/WCAG21/quickref/?currentsidebar=%23col_customize&levels=aaa) coverage.
42 |
43 | ## Contributing
44 |
45 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
46 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
47 | the rights to use your contribution. For details, visit https://cla.microsoft.com.
48 |
49 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
50 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
51 | provided by the bot. You will only need to do this once across all repos using our CLA.
52 |
53 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
54 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
55 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
56 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
40 |
41 |
--------------------------------------------------------------------------------
/csharp-selenium-webdriver-sample/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 | *.VC.VC.opendb
85 |
86 | # Visual Studio profiler
87 | *.psess
88 | *.vsp
89 | *.vspx
90 | *.sap
91 |
92 | # TFS 2012 Local Workspace
93 | $tf/
94 |
95 | # Guidance Automation Toolkit
96 | *.gpState
97 |
98 | # ReSharper is a .NET coding add-in
99 | _ReSharper*/
100 | *.[Rr]e[Ss]harper
101 | *.DotSettings.user
102 |
103 | # JustCode is a .NET coding add-in
104 | .JustCode
105 |
106 | # TeamCity is a build add-in
107 | _TeamCity*
108 |
109 | # DotCover is a Code Coverage Tool
110 | *.dotCover
111 |
112 | # NCrunch
113 | _NCrunch_*
114 | .*crunch*.local.xml
115 | nCrunchTemp_*
116 |
117 | # MightyMoose
118 | *.mm.*
119 | AutoTest.Net/
120 |
121 | # Web workbench (sass)
122 | .sass-cache/
123 |
124 | # Installshield output folder
125 | [Ee]xpress/
126 |
127 | # DocProject is a documentation generator add-in
128 | DocProject/buildhelp/
129 | DocProject/Help/*.HxT
130 | DocProject/Help/*.HxC
131 | DocProject/Help/*.hhc
132 | DocProject/Help/*.hhk
133 | DocProject/Help/*.hhp
134 | DocProject/Help/Html2
135 | DocProject/Help/html
136 |
137 | # Click-Once directory
138 | publish/
139 |
140 | # Publish Web Output
141 | *.[Pp]ublish.xml
142 | *.azurePubxml
143 | # TODO: Comment the next line if you want to checkin your web deploy settings
144 | # but database connection strings (with potential passwords) will be unencrypted
145 | *.pubxml
146 | *.publishproj
147 |
148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
149 | # checkin your Azure Web App publish settings, but sensitive information contained
150 | # in these scripts will be unencrypted
151 | PublishScripts/
152 |
153 | # NuGet Packages
154 | *.nupkg
155 | # The packages folder can be ignored because of Package Restore
156 | **/packages/*
157 | # except build/, which is used as an MSBuild target.
158 | !**/packages/build/
159 | # Uncomment if necessary however generally it will be regenerated when needed
160 | #!**/packages/repositories.config
161 | # NuGet v3's project.json files produces more ignoreable files
162 | *.nuget.props
163 | *.nuget.targets
164 |
165 | # Microsoft Azure Build Output
166 | csx/
167 | *.build.csdef
168 |
169 | # Microsoft Azure Emulator
170 | ecf/
171 | rcf/
172 |
173 | # Windows Store app package directories and files
174 | AppPackages/
175 | BundleArtifacts/
176 | Package.StoreAssociation.xml
177 | _pkginfo.txt
178 |
179 | # Visual Studio cache files
180 | # files ending in .cache can be ignored
181 | *.[Cc]ache
182 | # but keep track of directories ending in .cache
183 | !*.[Cc]ache/
184 |
185 | # Others
186 | ClientBin/
187 | ~$*
188 | *~
189 | *.dbmdl
190 | *.dbproj.schemaview
191 | *.pfx
192 | *.publishsettings
193 | node_modules/
194 | orleans.codegen.cs
195 |
196 | # Since there are multiple workflows, uncomment next line to ignore bower_components
197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
198 | #bower_components/
199 |
200 | # RIA/Silverlight projects
201 | Generated_Code/
202 |
203 | # Backup & report files from converting an old project file
204 | # to a newer Visual Studio version. Backup files are not needed,
205 | # because we have git ;-)
206 | _UpgradeReport_Files/
207 | Backup*/
208 | UpgradeLog*.XML
209 | UpgradeLog*.htm
210 |
211 | # SQL Server files
212 | *.mdf
213 | *.ldf
214 |
215 | # Business Intelligence projects
216 | *.rdl.data
217 | *.bim.layout
218 | *.bim_*.settings
219 |
220 | # Microsoft Fakes
221 | FakesAssemblies/
222 |
223 | # GhostDoc plugin setting file
224 | *.GhostDoc.xml
225 |
226 | # Node.js Tools for Visual Studio
227 | .ntvs_analysis.dat
228 |
229 | # Visual Studio 6 build log
230 | *.plg
231 |
232 | # Visual Studio 6 workspace options file
233 | *.opt
234 |
235 | # Visual Studio LightSwitch build output
236 | **/*.HTMLClient/GeneratedArtifacts
237 | **/*.DesktopClient/GeneratedArtifacts
238 | **/*.DesktopClient/ModelManifest.xml
239 | **/*.Server/GeneratedArtifacts
240 | **/*.Server/ModelManifest.xml
241 | _Pvt_Extensions
242 |
243 | # Paket dependency manager
244 | .paket/paket.exe
245 | paket-files/
246 |
247 | # FAKE - F# Make
248 | .fake/
249 |
250 | # JetBrains Rider
251 | .idea/
252 | *.sln.iml
253 |
254 | # Solution File for the purpose of this project only
255 | *.sln
--------------------------------------------------------------------------------
/csharp-selenium-webdriver-sample/CSharpSeleniumWebdriverSample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {E6205F43-94B0-462C-AA5B-AE816794E95A}
4 | net6.0
5 | CSharpSeleniumWebdriverSample
6 | CSharpSeleniumWebdriverSample
7 |
8 |
9 |
10 | Always
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/csharp-selenium-webdriver-sample/README.md:
--------------------------------------------------------------------------------
1 | # CSharpSeleniumWebdriverSample
2 |
3 | This sample demonstrates how you might set up a C# Project with an Azure Pipelines build that runs end to end accessibility tests in a browser.
4 |
5 | ## Getting Started
6 |
7 | The individual files in the sample contain comments that explain the important parts of each file in context.
8 |
9 | Some good places to start reading are:
10 |
11 | * [SamplePageTests.cs](./SamplePageTests.cs): C# test file that opens [SamplePage.html](./SamplePage.html) in a browser with Selenium and runs accessibility scans against it
12 | * [azure-pipelines.yml](./azure-pipelines.yml): Azure Pipelines config file that sets up our Continuous Integration and Pull Request builds
13 |
14 | ## Tools and libraries used
15 |
16 | The key tools and libraries this sample demonstrates are:
17 |
18 | * [Selenium.WebDriver](https://www.seleniumhq.org), the .NET library for Selenium, a tool for automating interactions with different web browsers.
19 | * [Selenium.Axe](https://github.com/TroyWalshProf/SeleniumAxeDotnet), a .NET library for running accessibility scans on web pages by using Selenium.WebDriver to run the [axe-core](https://github.com/dequelabs/axe-core) accessibility scanning engine.
20 | * [Azure Pipelines](https://azure.microsoft.com/en-us/services/devops/pipelines/) to run the tests in a CI build with every Pull Request.
21 |
22 | This sample also uses a few other tools and libraries which are less important; if you use a different test framework or a different version of .NET, you can still follow along with most of the sample.
23 |
24 | * [.NET Core](https://dotnet.microsoft.com) to build/run the code.
25 | * None of the libraries or C# code in the sample are specific to .NET Core; if your project uses the full .NET Framework, you can still follow along with the sample!
26 | * [MSTest](https://github.com/microsoft/testfx) as our test framework.
27 | * None of the other libraries we're using require this particular framework; you can still follow along with the sample using NUnit, xUnit, or any other test framework you like.
28 | * [Chrome](https://google.com/chrome) (with [Selenium.WebDriver.ChromeDriver](https://github.com/jsakamoto/nupkg-selenium-webdriver-chromedriver/)) and [Firefox](https://www.mozilla.org/firefox/) (with [Selenium.WebDriver.GeckoDriver](https://github.com/jsakamoto/nupkg-selenium-webdriver-geckodriver/)) as our test browsers
29 | * Selenium supports many different browsers and operating systems; use whichever combination is most important for your product!
30 | * [FluentAssertions](https://fluentassertions.com/) to write test assertions
31 | * We like FluentAssertions because it gives great error messages out-of-the-box with Selenium.Axe. But you can still follow the rest of the sample if you prefer a different assertion style!
32 |
33 | ## See it in action on your local machine
34 |
35 | 1. Install the [.NET Core SDK](https://dotnet.microsoft.com/download)
36 | 1. Install the stable version of [Chrome](https://www.google.com/chrome/)
37 | 1. Install the stable version of [Firefox](https://www.mozilla.org/en-US/firefox/)
38 | 1. Clone this sample repository
39 |
40 | ```sh
41 | git clone https://github.com/microsoft/axe-pipelines-samples
42 | ```
43 |
44 | 1. Run the tests
45 |
46 | Filter to only run passing tests:
47 |
48 | ```sh
49 | cd ./axe-pipelines-samples/csharp-selenium-webdriver-sample
50 | dotnet test --filter TestCategory!=IntentionallyFailsAsAnExample
51 | ```
52 |
53 | 
54 |
55 | Run all tests (both passing and failing):
56 |
57 | ```sh
58 | cd ./axe-pipelines-samples/csharp-selenium-webdriver-sample
59 | dotnet test
60 | ```
61 |
62 | 
63 |
64 | ## See it in action in Azure Pipelines
65 |
66 | * Example build with failures: [](https://dev.azure.com/accessibility-insights/axe-pipelines-samples/_build/latest?definitionId=33&branchName=main)
67 | * Example build without failures: [](https://dev.azure.com/accessibility-insights/axe-pipelines-samples/_build/latest?definitionId=32&branchName=main)
68 |
69 |
73 | The accessibility tests run as part of the `dotnet test` build step:
74 |
75 | [](https://dev.azure.com/accessibility-insights/axe-pipelines-samples/_build/results?buildId=2338&view=logs&j=12f1170f-54f2-53f3-20dd-22fc7dff55f9)
76 |
77 | The test pass/fail results display in the Tests tab of the build logs:
78 |
79 | [](https://dev.azure.com/accessibility-insights/axe-pipelines-samples/_build/results?buildId=2338&view=ms.vss-test-web.build-test-results-tab&runId=6512&resultId=100000&paneView=debug)
80 |
--------------------------------------------------------------------------------
/csharp-selenium-webdriver-sample/Resources/screenshot-dotnet-test-failure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/axe-pipelines-samples/32d272945fc3056c0cc35740e85b0a8306346cb4/csharp-selenium-webdriver-sample/Resources/screenshot-dotnet-test-failure.png
--------------------------------------------------------------------------------
/csharp-selenium-webdriver-sample/Resources/screenshot-dotnet-test-success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/axe-pipelines-samples/32d272945fc3056c0cc35740e85b0a8306346cb4/csharp-selenium-webdriver-sample/Resources/screenshot-dotnet-test-success.png
--------------------------------------------------------------------------------
/csharp-selenium-webdriver-sample/Resources/screenshot-logs-tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/axe-pipelines-samples/32d272945fc3056c0cc35740e85b0a8306346cb4/csharp-selenium-webdriver-sample/Resources/screenshot-logs-tab.png
--------------------------------------------------------------------------------
/csharp-selenium-webdriver-sample/Resources/screenshot-tests-tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/axe-pipelines-samples/32d272945fc3056c0cc35740e85b0a8306346cb4/csharp-selenium-webdriver-sample/Resources/screenshot-tests-tab.png
--------------------------------------------------------------------------------
/csharp-selenium-webdriver-sample/SamplePage.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Example page with some accessibility issues
5 |
6 |
7 |
8 | This is a static sample page with some accessibility issues
9 | Here are some examples of content without axe-core violations
10 | There's nothing wrong with this paragraph!
11 | There's also nothing wrong with this paragraph!
12 |
13 | Here are some examples of content with different types of axe-core violations
14 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/csharp-selenium-webdriver-sample/SamplePageTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | // This sample happens to use .NET Core, but you can use whichever .NET version makes sense for your project.
5 | // Everything we're demonstrating would also work in .NET Framework 4.5+ with no modifications.
6 | using System;
7 | using System.IO;
8 | // This sample happens to use MSTest, but you can use whichever test framework you like.
9 | // Everything we're demonstrating would also work with xUnit, NUnit, or any other test framework.
10 | using Microsoft.VisualStudio.TestTools.UnitTesting;
11 | // If you're using Selenium already, you're probably already using these.
12 | using OpenQA.Selenium;
13 | using OpenQA.Selenium.Support.UI;
14 | // These are the important new libraries we're demonstrating.
15 | // You'll probably need to add new NuGet package references for these.
16 | using Selenium.Axe;
17 | using FluentAssertions;
18 |
19 | namespace CSharpSeleniumWebdriverSample
20 | {
21 | [TestClass]
22 | public class SamplePageTests
23 | {
24 | #region Example test methods
25 |
26 | // This test case shows the most basic example: run an accessibility scan on a page and assert that there are no violations.
27 | [TestMethod]
28 | [TestCategory("IntentionallyFailsAsAnExample")]
29 | public void TestAccessibilityOfPage()
30 | {
31 | AxeResult axeResult = new AxeBuilder(_webDriver)
32 | // This WithTags directive restricts Axe to only run tests that detect known violations of WCAG 2.1 A and AA rules
33 | // (similar to what Accessibility Insights reports). If you omit this, Axe will additionally run several "best practice"
34 | // rules, which are good ideas to check for periodically but may report false positives in certain edge cases.
35 | //
36 | // For complete documentation of which rule IDs and tags axe supports, see:
37 | // * summary of rules with IDs and tags: https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md
38 | // * full reference documentation for each rule: https://dequeuniversity.com/rules/axe
39 | .WithTags("wcag2a", "wcag2aa", "wcag21a", "wcag21aa")
40 | .Analyze();
41 |
42 | // axeResult.Violations is an array of all the accessibility violations the scan found; the easiest way to assert
43 | // that a scan came back clean is to assert that the Violations array is empty. You can do this with the built in
44 | // MSTest assertions like this:
45 | //
46 | // Assert.AreEqual(0, axeResult.Violations.Length);
47 | //
48 | // However, we don't recommend using Assert.AreEqual for this because it doesn't give very useful error messages if
49 | // it does detect a violation; the error message will just say "expected 0 but found 1".
50 | //
51 | // We recommend using FluentAssertions instead; its default behavior gives much better error messages that include
52 | // full descriptions of accessibility issues, including links to detailed guidance at https://dequeuniversity.com
53 | // and CSS selector paths that exactly identify the element on the page with the issue.
54 | axeResult.Error.Should().BeNull();
55 |
56 | // Our PR builds do not change the presence or absence of accessibility issues, so we special case
57 | // our PR build tests to expect the errors. This is not recommended for most projects, but since the
58 | // check takes effect only if the ACCESSIBILITY_ERRORS_ARE_EXPECTED_IN_PR_BUILD variable is set to
59 | // true within the pipeline, you may safely copy this code and the special case will be ignored.
60 | if (AccessibilityErrorsAreExpectedInThisBuild())
61 | {
62 | axeResult.Violations.Should().NotBeEmpty();
63 | }
64 | else
65 | {
66 | axeResult.Violations.Should().BeEmpty();
67 | }
68 | }
69 |
70 | // This test case shows 2 options for scanning specific elements within a page, rather than an entire page.
71 | [TestMethod]
72 | public void TestAccessibilityOfIndividualElements()
73 | {
74 | // Both of these 2 options work equally well; which one to use is a matter of preference.
75 |
76 | // Option 1: using Selenium's FindElement to identify the element to test
77 | //
78 | // This can be simpler if your test already had to find the element for earlier assertions, or if you want to test
79 | // an element that is hard to identify using a CSS selector.
80 | IWebElement elementUnderTest = _webDriver.FindElement(By.Id("id-of-example-accessible-element"));
81 |
82 | AxeResult axeResultWithAnalyzeWebElement = new AxeBuilder(_webDriver)
83 | .WithTags("wcag2a", "wcag2aa", "wcag21a", "wcag21aa")
84 | .Analyze(elementUnderTest);
85 |
86 | axeResultWithAnalyzeWebElement.Error.Should().BeNull();
87 | axeResultWithAnalyzeWebElement.Violations.Should().BeEmpty();
88 |
89 | // Option 2: using AxeBuilder.Include
90 | //
91 | // This can be simpler if you need to test multiple elements at once or need to deal with