@techsio/storybook-better-a11y 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/{visionSimulatorFilters.js → 100.js} +23 -1
  2. package/dist/{apcaChecker.js → 699.js} +253 -1
  3. package/dist/index.js +6 -5
  4. package/dist/manager.js +1540 -11
  5. package/dist/postinstall.js +1 -1
  6. package/dist/preview.js +1 -68
  7. package/dist/rslib-runtime.js +37 -0
  8. package/package.json +1 -1
  9. package/dist/AccessibilityRuleMaps.js +0 -532
  10. package/dist/a11yRunner.js +0 -105
  11. package/dist/a11yRunner.test.js +0 -21
  12. package/dist/a11yRunnerUtils.js +0 -30
  13. package/dist/a11yRunnerUtils.test.js +0 -61
  14. package/dist/apcaChecker.test.js +0 -124
  15. package/dist/axeRuleMappingHelper.js +0 -4
  16. package/dist/components/A11YPanel.js +0 -140
  17. package/dist/components/A11YPanel.stories.js +0 -198
  18. package/dist/components/A11YPanel.test.js +0 -110
  19. package/dist/components/A11yContext.js +0 -438
  20. package/dist/components/A11yContext.test.js +0 -277
  21. package/dist/components/Report/Details.js +0 -169
  22. package/dist/components/Report/Report.js +0 -106
  23. package/dist/components/Report/Report.stories.js +0 -86
  24. package/dist/components/Tabs.js +0 -54
  25. package/dist/components/TestDiscrepancyMessage.js +0 -55
  26. package/dist/components/TestDiscrepancyMessage.stories.js +0 -40
  27. package/dist/components/VisionSimulator.js +0 -83
  28. package/dist/components/VisionSimulator.stories.js +0 -56
  29. package/dist/constants.js +0 -25
  30. package/dist/manager.test.js +0 -86
  31. package/dist/params.js +0 -0
  32. package/dist/preview.test.js +0 -215
  33. package/dist/results.mock.js +0 -874
  34. package/dist/types.js +0 -6
  35. package/dist/utils.js +0 -21
  36. package/dist/withVisionSimulator.js +0 -41
@@ -1,3 +1,25 @@
1
+ const ADDON_ID = 'storybook/a11y';
2
+ const PANEL_ID = `${ADDON_ID}/panel`;
3
+ "a11y";
4
+ "vision";
5
+ const RESULT = `${ADDON_ID}/result`;
6
+ const REQUEST = `${ADDON_ID}/request`;
7
+ const RUNNING = `${ADDON_ID}/running`;
8
+ const ERROR = `${ADDON_ID}/error`;
9
+ const MANUAL = `${ADDON_ID}/manual`;
10
+ const SELECT = `${ADDON_ID}/select`;
11
+ const DOCUMENTATION_LINK = 'writing-tests/accessibility-testing';
12
+ const DOCUMENTATION_DISCREPANCY_LINK = `${DOCUMENTATION_LINK}#why-are-my-tests-failing-in-different-environments`;
13
+ const EVENTS = {
14
+ RESULT: RESULT,
15
+ REQUEST: REQUEST,
16
+ RUNNING: RUNNING,
17
+ ERROR: ERROR,
18
+ MANUAL: MANUAL,
19
+ SELECT: SELECT
20
+ };
21
+ const STATUS_TYPE_ID_COMPONENT_TEST = 'storybook/component-test';
22
+ const STATUS_TYPE_ID_A11Y = 'storybook/a11y';
1
23
  const filters = {
2
24
  blurred: {
3
25
  label: 'Blurred vision',
@@ -97,4 +119,4 @@ const filterDefs = `<svg id="storybook-a11y-vision-filters" style="display: none
97
119
  </filter>
98
120
  </defs>
99
121
  </svg>`;
100
- export { filterDefs, filters };
122
+ export { ADDON_ID, DOCUMENTATION_DISCREPANCY_LINK, EVENTS, PANEL_ID, STATUS_TYPE_ID_A11Y, STATUS_TYPE_ID_COMPONENT_TEST, filterDefs, filters };
@@ -1,4 +1,44 @@
1
+ import { __webpack_require__ } from "./rslib-runtime.js";
2
+ import { expect } from "storybook/test";
3
+ import { ElementA11yParameterError } from "storybook/internal/preview-errors";
1
4
  import { global } from "@storybook/global";
5
+ import { addons, useCallback, useEffect, waitForAnimations } from "storybook/preview-api";
6
+ import { EVENTS, filters, filterDefs, PANEL_ID } from "./100.js";
7
+ var preview_namespaceObject = {};
8
+ __webpack_require__.r(preview_namespaceObject);
9
+ __webpack_require__.d(preview_namespaceObject, {
10
+ afterEach: ()=>afterEach,
11
+ decorators: ()=>decorators,
12
+ initialGlobals: ()=>initialGlobals,
13
+ parameters: ()=>preview_parameters
14
+ });
15
+ const { document: a11yRunnerUtils_document } = global;
16
+ const withLinkPaths = (results, storyId)=>{
17
+ const pathname = a11yRunnerUtils_document.location.pathname.replace(/iframe\.html$/, '');
18
+ const enhancedResults = {
19
+ ...results
20
+ };
21
+ const propertiesToAugment = [
22
+ 'incomplete',
23
+ 'passes',
24
+ 'violations'
25
+ ];
26
+ propertiesToAugment.forEach((key)=>{
27
+ if (Array.isArray(results[key])) enhancedResults[key] = results[key].map((result)=>({
28
+ ...result,
29
+ nodes: result.nodes.map((node, index)=>{
30
+ const id = `${key}.${result.id}.${index + 1}`;
31
+ const linkPath = `${pathname}?path=/story/${storyId}&addonPanel=${PANEL_ID}&a11ySelection=${id}`;
32
+ return {
33
+ id,
34
+ ...node,
35
+ linkPath
36
+ };
37
+ })
38
+ }));
39
+ });
40
+ return enhancedResults;
41
+ };
2
42
  const { document: apcaChecker_document } = global;
3
43
  const DEFAULT_APCA_OPTIONS = {
4
44
  level: 'bronze',
@@ -285,4 +325,216 @@ function getImpact(contrastValue, threshold, maxContrast) {
285
325
  if (difference > 10) return 'moderate';
286
326
  return 'minor';
287
327
  }
288
- export { runAPCACheck };
328
+ const { document: a11yRunner_document } = global;
329
+ const channel = addons.getChannel();
330
+ const DEFAULT_PARAMETERS = {
331
+ config: {},
332
+ options: {}
333
+ };
334
+ const DISABLED_RULES = [
335
+ 'region'
336
+ ];
337
+ const queue = [];
338
+ let isRunning = false;
339
+ const runNext = async ()=>{
340
+ if (0 === queue.length) {
341
+ isRunning = false;
342
+ return;
343
+ }
344
+ isRunning = true;
345
+ const next = queue.shift();
346
+ if (next) await next();
347
+ runNext();
348
+ };
349
+ const run = async (input = DEFAULT_PARAMETERS, storyId)=>{
350
+ const axeCore = await import("axe-core");
351
+ const axe = axeCore?.default || globalThis.axe;
352
+ const { config = {}, options = {} } = input;
353
+ if (input.element) throw new ElementA11yParameterError();
354
+ const context = {
355
+ include: a11yRunner_document?.body,
356
+ exclude: [
357
+ '.sb-wrapper',
358
+ '#storybook-docs',
359
+ '#storybook-highlights-root'
360
+ ]
361
+ };
362
+ if (input.context) {
363
+ const hasInclude = 'object' == typeof input.context && 'include' in input.context && void 0 !== input.context.include;
364
+ const hasExclude = 'object' == typeof input.context && 'exclude' in input.context && void 0 !== input.context.exclude;
365
+ if (hasInclude) context.include = input.context.include;
366
+ else if (!hasInclude && !hasExclude) context.include = input.context;
367
+ if (hasExclude) context.exclude = context.exclude.concat(input.context.exclude);
368
+ }
369
+ axe.reset();
370
+ const configWithDefault = {
371
+ ...config,
372
+ rules: [
373
+ ...DISABLED_RULES.map((id)=>({
374
+ id,
375
+ enabled: false
376
+ })),
377
+ ...config?.rules ?? []
378
+ ]
379
+ };
380
+ axe.configure(configWithDefault);
381
+ return new Promise((resolve, reject)=>{
382
+ const highlightsRoot = a11yRunner_document?.getElementById('storybook-highlights-root');
383
+ if (highlightsRoot) highlightsRoot.style.display = 'none';
384
+ const task = async ()=>{
385
+ try {
386
+ const result = await axe.run(context, options);
387
+ let contextElement = a11yRunner_document;
388
+ if (context.include instanceof Element) contextElement = context.include;
389
+ else if (Array.isArray(context.include)) {
390
+ const first = context.include[0];
391
+ if (first instanceof Element) contextElement = first;
392
+ else if ('string' == typeof first) contextElement = a11yRunner_document.querySelector(first) || a11yRunner_document;
393
+ } else if ('string' == typeof context.include) contextElement = a11yRunner_document.querySelector(context.include) || a11yRunner_document;
394
+ const excludeSelectors = Array.isArray(context.exclude) ? context.exclude.filter((value)=>'string' == typeof value) : 'string' == typeof context.exclude ? [
395
+ context.exclude
396
+ ] : [];
397
+ const apcaResult = await runAPCACheck(contextElement, input.apca, excludeSelectors);
398
+ if (apcaResult.nodes.length > 0) result.violations.push(apcaResult);
399
+ else result.passes.push(apcaResult);
400
+ const resultWithLinks = withLinkPaths(result, storyId);
401
+ globalThis.__TECHSIO_A11Y_RESULTS__ = {
402
+ storyId,
403
+ results: resultWithLinks,
404
+ timestamp: Date.now()
405
+ };
406
+ resolve(resultWithLinks);
407
+ } catch (error) {
408
+ reject(error);
409
+ }
410
+ };
411
+ queue.push(task);
412
+ if (!isRunning) runNext();
413
+ if (highlightsRoot) highlightsRoot.style.display = '';
414
+ });
415
+ };
416
+ channel.on(EVENTS.MANUAL, async (storyId, input = DEFAULT_PARAMETERS)=>{
417
+ try {
418
+ await waitForAnimations();
419
+ const result = await run(input, storyId);
420
+ const resultJson = JSON.parse(JSON.stringify(result));
421
+ channel.emit(EVENTS.RESULT, resultJson, storyId);
422
+ } catch (error) {
423
+ channel.emit(EVENTS.ERROR, error);
424
+ }
425
+ });
426
+ function getIsVitestStandaloneRun() {
427
+ try {
428
+ return 'false' === ({
429
+ MODE: "production",
430
+ DEV: false,
431
+ PROD: true,
432
+ BASE_URL: "/",
433
+ ASSET_PREFIX: "auto"
434
+ }).VITEST_STORYBOOK;
435
+ } catch (e) {
436
+ return false;
437
+ }
438
+ }
439
+ const knownFilters = Object.values(filters).map((f)=>f.filter);
440
+ const knownFiltersRegExp = new RegExp(`\\b(${knownFilters.join('|')})\\b`, 'g');
441
+ const withVisionSimulator = (StoryFn, { globals })=>{
442
+ const { vision } = globals;
443
+ const applyVisionFilter = useCallback(()=>{
444
+ const existingFilters = document.body.style.filter.replaceAll(knownFiltersRegExp, '').trim();
445
+ const visionFilter = filters[vision]?.filter;
446
+ if (visionFilter && document.body.classList.contains('sb-show-main')) if (existingFilters && 'none' !== existingFilters) document.body.style.filter = `${existingFilters} ${visionFilter}`;
447
+ else document.body.style.filter = visionFilter;
448
+ else document.body.style.filter = existingFilters || 'none';
449
+ return ()=>document.body.style.filter = existingFilters || 'none';
450
+ }, [
451
+ vision
452
+ ]);
453
+ useEffect(()=>{
454
+ const cleanup = applyVisionFilter();
455
+ const observer = new MutationObserver(()=>applyVisionFilter());
456
+ observer.observe(document.body, {
457
+ attributeFilter: [
458
+ 'class'
459
+ ]
460
+ });
461
+ return ()=>{
462
+ cleanup();
463
+ observer.disconnect();
464
+ };
465
+ }, [
466
+ applyVisionFilter
467
+ ]);
468
+ useEffect(()=>{
469
+ document.body.insertAdjacentHTML('beforeend', filterDefs);
470
+ return ()=>{
471
+ const filterDefsElement = document.getElementById('storybook-a11y-vision-filters');
472
+ filterDefsElement?.parentElement?.removeChild(filterDefsElement);
473
+ };
474
+ }, []);
475
+ return StoryFn();
476
+ };
477
+ let vitestMatchersExtended = false;
478
+ const decorators = [
479
+ withVisionSimulator
480
+ ];
481
+ const afterEach = async ({ id: storyId, reporting, parameters, globals, viewMode })=>{
482
+ const a11yParameter = parameters.a11y;
483
+ const a11yGlobals = globals.a11y;
484
+ const shouldRunEnvironmentIndependent = a11yParameter?.disable !== true && a11yParameter?.test !== 'off' && a11yGlobals?.manual !== true;
485
+ const getMode = ()=>{
486
+ switch(a11yParameter?.test){
487
+ case 'todo':
488
+ return 'warning';
489
+ case 'error':
490
+ default:
491
+ return 'failed';
492
+ }
493
+ };
494
+ if (shouldRunEnvironmentIndependent && 'story' === viewMode) try {
495
+ const result = await run(a11yParameter, storyId);
496
+ if (result) {
497
+ const hasViolations = (result?.violations.length ?? 0) > 0;
498
+ reporting.addReport({
499
+ type: 'a11y',
500
+ version: 1,
501
+ result,
502
+ status: hasViolations ? getMode() : 'passed'
503
+ });
504
+ if (getIsVitestStandaloneRun()) {
505
+ if (hasViolations && 'failed' === getMode()) {
506
+ if (!vitestMatchersExtended) {
507
+ const { toHaveNoViolations } = await import("vitest-axe/matchers");
508
+ expect.extend({
509
+ toHaveNoViolations
510
+ });
511
+ vitestMatchersExtended = true;
512
+ }
513
+ expect(result).toHaveNoViolations();
514
+ }
515
+ }
516
+ }
517
+ } catch (e) {
518
+ reporting.addReport({
519
+ type: 'a11y',
520
+ version: 1,
521
+ result: {
522
+ error: e
523
+ },
524
+ status: 'failed'
525
+ });
526
+ if (getIsVitestStandaloneRun()) throw e;
527
+ }
528
+ };
529
+ const initialGlobals = {
530
+ a11y: {
531
+ manual: false
532
+ },
533
+ vision: void 0
534
+ };
535
+ const preview_parameters = {
536
+ a11y: {
537
+ test: 'todo'
538
+ }
539
+ };
540
+ export { afterEach, decorators, initialGlobals, preview_namespaceObject, preview_parameters as parameters };
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { definePreviewAddon } from "storybook/internal/csf";
2
- import { PARAM_KEY } from "./constants.js";
3
- export * from "./params.js";
4
- import * as __rspack_external__preview_js_3b21eac2 from "./preview.js";
5
- const src = ()=>definePreviewAddon(__rspack_external__preview_js_3b21eac2);
6
- export { PARAM_KEY, src as default };
2
+ import { preview_namespaceObject } from "./699.js";
3
+ import "./100.js";
4
+ const src = ()=>definePreviewAddon(preview_namespaceObject);
5
+ var src_PARAM_KEY = "a11y";
6
+ export default src;
7
+ export { src_PARAM_KEY as PARAM_KEY };