@techsio/storybook-better-a11y 0.0.4 → 0.0.6

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 (38) hide show
  1. package/dist/AccessibilityRuleMaps.js +532 -0
  2. package/dist/a11yRunner.js +105 -0
  3. package/dist/a11yRunner.test.js +21 -0
  4. package/dist/a11yRunnerUtils.js +30 -0
  5. package/dist/a11yRunnerUtils.test.js +61 -0
  6. package/dist/{699.js → apcaChecker.js} +1 -255
  7. package/dist/apcaChecker.test.js +124 -0
  8. package/dist/axeRuleMappingHelper.js +4 -0
  9. package/dist/components/A11YPanel.js +140 -0
  10. package/dist/components/A11YPanel.stories.js +198 -0
  11. package/dist/components/A11YPanel.test.js +110 -0
  12. package/dist/components/A11yContext.js +438 -0
  13. package/dist/components/A11yContext.test.js +277 -0
  14. package/dist/components/Report/Details.js +169 -0
  15. package/dist/components/Report/Report.js +106 -0
  16. package/dist/components/Report/Report.stories.js +86 -0
  17. package/dist/components/Tabs.js +54 -0
  18. package/dist/components/TestDiscrepancyMessage.js +55 -0
  19. package/dist/components/TestDiscrepancyMessage.stories.js +40 -0
  20. package/dist/components/VisionSimulator.js +83 -0
  21. package/dist/components/VisionSimulator.stories.js +56 -0
  22. package/dist/constants.js +25 -0
  23. package/dist/index.js +5 -6
  24. package/dist/manager.js +11 -1540
  25. package/dist/manager.test.js +86 -0
  26. package/dist/params.js +0 -0
  27. package/dist/postinstall.js +1 -1
  28. package/dist/preview.js +68 -1
  29. package/dist/preview.test.js +215 -0
  30. package/dist/results.mock.js +874 -0
  31. package/dist/types.js +6 -0
  32. package/dist/utils.js +21 -0
  33. package/dist/{100.js → visionSimulatorFilters.js} +1 -23
  34. package/dist/withVisionSimulator.js +41 -0
  35. package/package.json +1 -1
  36. package/dist/212.js +0 -1965
  37. package/dist/212.js.LICENSE.txt +0 -19
  38. package/dist/rslib-runtime.js +0 -37
@@ -0,0 +1,86 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { PANEL_ID } from "./constants.js";
3
+ import "./manager.js";
4
+ import * as __rspack_external_storybook_manager_api_d834c1f5 from "storybook/manager-api";
5
+ vi.mock('storybook/manager-api');
6
+ const mockedApi = vi.mocked(__rspack_external_storybook_manager_api_d834c1f5);
7
+ mockedApi.useStorybookApi = vi.fn(()=>({
8
+ getSelectedPanel: vi.fn()
9
+ }));
10
+ mockedApi.useAddonState = vi.fn();
11
+ const mockedAddons = vi.mocked(__rspack_external_storybook_manager_api_d834c1f5.addons);
12
+ const registrationImpl = mockedAddons.register.mock.calls[0][1];
13
+ const isPanel = (input)=>input.type === __rspack_external_storybook_manager_api_d834c1f5.types.PANEL;
14
+ describe('A11yManager', ()=>{
15
+ it('should register the panels', ()=>{
16
+ registrationImpl(mockedApi);
17
+ expect(mockedAddons.add.mock.calls).toHaveLength(2);
18
+ expect(mockedAddons.add).toHaveBeenCalledWith(PANEL_ID, expect.anything());
19
+ const panel = mockedAddons.add.mock.calls.map(([_, def])=>def).find(({ type })=>type === __rspack_external_storybook_manager_api_d834c1f5.types.PANEL);
20
+ const tool = mockedAddons.add.mock.calls.map(([_, def])=>def).find(({ type })=>type === __rspack_external_storybook_manager_api_d834c1f5.types.TOOL);
21
+ expect(panel).toBeDefined();
22
+ expect(tool).toBeDefined();
23
+ });
24
+ it('should compute title with no issues', ()=>{
25
+ mockedApi.useAddonState.mockImplementation(()=>[
26
+ {
27
+ results: void 0
28
+ }
29
+ ]);
30
+ registrationImpl(__rspack_external_storybook_manager_api_d834c1f5);
31
+ const title = mockedAddons.add.mock.calls.map(([_, def])=>def).find(isPanel)?.title;
32
+ expect(title()).toMatchInlineSnapshot(`
33
+ <div
34
+ style={
35
+ {
36
+ "alignItems": "center",
37
+ "display": "flex",
38
+ "gap": 6,
39
+ }
40
+ }
41
+ >
42
+ <span>
43
+ Accessibility
44
+ </span>
45
+ </div>
46
+ `);
47
+ });
48
+ it('should compute title with issues', ()=>{
49
+ mockedApi.useAddonState.mockImplementation(()=>[
50
+ {
51
+ results: {
52
+ violations: [
53
+ {}
54
+ ],
55
+ incomplete: [
56
+ {},
57
+ {}
58
+ ]
59
+ }
60
+ }
61
+ ]);
62
+ registrationImpl(mockedApi);
63
+ const title = mockedAddons.add.mock.calls.map(([_, def])=>def).find(isPanel)?.title;
64
+ expect(title()).toMatchInlineSnapshot(`
65
+ <div
66
+ style={
67
+ {
68
+ "alignItems": "center",
69
+ "display": "flex",
70
+ "gap": 6,
71
+ }
72
+ }
73
+ >
74
+ <span>
75
+ Accessibility
76
+ </span>
77
+ <Badge
78
+ compact={true}
79
+ status="neutral"
80
+ >
81
+ 3
82
+ </Badge>
83
+ </div>
84
+ `);
85
+ });
86
+ });
package/dist/params.js ADDED
File without changes
@@ -18,4 +18,4 @@ async function postinstall(options) {
18
18
  args
19
19
  });
20
20
  }
21
- export default postinstall;
21
+ export { postinstall as default };
package/dist/preview.js CHANGED
@@ -1 +1,68 @@
1
- export { afterEach, decorators, initialGlobals, parameters } from "./699.js";
1
+ import { expect } from "storybook/test";
2
+ import { run } from "./a11yRunner.js";
3
+ import { getIsVitestStandaloneRun } from "./utils.js";
4
+ import { withVisionSimulator } from "./withVisionSimulator.js";
5
+ let vitestMatchersExtended = false;
6
+ const decorators = [
7
+ withVisionSimulator
8
+ ];
9
+ const afterEach = async ({ id: storyId, reporting, parameters, globals, viewMode })=>{
10
+ const a11yParameter = parameters.a11y;
11
+ const a11yGlobals = globals.a11y;
12
+ const shouldRunEnvironmentIndependent = a11yParameter?.disable !== true && a11yParameter?.test !== 'off' && a11yGlobals?.manual !== true;
13
+ const getMode = ()=>{
14
+ switch(a11yParameter?.test){
15
+ case 'todo':
16
+ return 'warning';
17
+ case 'error':
18
+ default:
19
+ return 'failed';
20
+ }
21
+ };
22
+ if (shouldRunEnvironmentIndependent && 'story' === viewMode) try {
23
+ const result = await run(a11yParameter, storyId);
24
+ if (result) {
25
+ const hasViolations = (result?.violations.length ?? 0) > 0;
26
+ reporting.addReport({
27
+ type: 'a11y',
28
+ version: 1,
29
+ result,
30
+ status: hasViolations ? getMode() : 'passed'
31
+ });
32
+ if (getIsVitestStandaloneRun()) {
33
+ if (hasViolations && 'failed' === getMode()) {
34
+ if (!vitestMatchersExtended) {
35
+ const { toHaveNoViolations } = await import("vitest-axe/matchers");
36
+ expect.extend({
37
+ toHaveNoViolations
38
+ });
39
+ vitestMatchersExtended = true;
40
+ }
41
+ expect(result).toHaveNoViolations();
42
+ }
43
+ }
44
+ }
45
+ } catch (e) {
46
+ reporting.addReport({
47
+ type: 'a11y',
48
+ version: 1,
49
+ result: {
50
+ error: e
51
+ },
52
+ status: 'failed'
53
+ });
54
+ if (getIsVitestStandaloneRun()) throw e;
55
+ }
56
+ };
57
+ const initialGlobals = {
58
+ a11y: {
59
+ manual: false
60
+ },
61
+ vision: void 0
62
+ };
63
+ const preview_parameters = {
64
+ a11y: {
65
+ test: 'todo'
66
+ }
67
+ };
68
+ export { afterEach, decorators, initialGlobals, preview_parameters as parameters };
@@ -0,0 +1,215 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { run } from "./a11yRunner.js";
3
+ import { afterEach } from "./preview.js";
4
+ import { getIsVitestRunning, getIsVitestStandaloneRun } from "./utils.js";
5
+ const mocks = vi.hoisted(()=>({
6
+ getIsVitestRunning: vi.fn(),
7
+ getIsVitestStandaloneRun: vi.fn()
8
+ }));
9
+ vi.mock(import("./a11yRunner.js"));
10
+ vi.mock(import("./utils.js"), async (importOriginal)=>{
11
+ const mod = await importOriginal();
12
+ return {
13
+ ...mod,
14
+ getIsVitestRunning: mocks.getIsVitestRunning,
15
+ getIsVitestStandaloneRun: mocks.getIsVitestStandaloneRun
16
+ };
17
+ });
18
+ const mockedRun = vi.mocked(run);
19
+ const violations = [
20
+ {
21
+ id: 'color-contrast',
22
+ impact: 'serious',
23
+ tags: '_duplicate_["args","0","reporters","0","result","passes","12","tags"]',
24
+ description: 'Ensures the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds',
25
+ help: 'Elements must meet minimum color contrast ratio thresholds',
26
+ helpUrl: 'https://dequeuniversity.com/rules/axe/4.8/color-contrast?application=axeAPI',
27
+ nodes: [
28
+ {
29
+ any: [
30
+ {
31
+ id: 'color-contrast',
32
+ data: {
33
+ fgColor: '#029cfd',
34
+ bgColor: '#f6f9fc',
35
+ contrastRatio: 2.76,
36
+ fontSize: '10.5pt (14px)',
37
+ fontWeight: 'normal',
38
+ messageKey: null,
39
+ expectedContrastRatio: '4.5:1',
40
+ shadowColor: '_undefined_'
41
+ },
42
+ relatedNodes: [
43
+ {
44
+ html: '<div class="css-1av19vu">',
45
+ target: [
46
+ '.css-1av19vu'
47
+ ]
48
+ }
49
+ ],
50
+ impact: 'serious',
51
+ message: 'Element has insufficient color contrast of 2.76 (foreground color: #029cfd, background color: #f6f9fc, font size: 10.5pt (14px), font weight: normal). Expected contrast ratio of 4.5:1',
52
+ '_constructor-name_': 'CheckResult'
53
+ }
54
+ ],
55
+ all: [],
56
+ none: [],
57
+ impact: 'serious',
58
+ html: '<span class="css-1mjgzsp">',
59
+ target: [
60
+ '.css-1mjgzsp'
61
+ ],
62
+ failureSummary: 'Fix any of the following:\n Element has insufficient color contrast of 2.76 (foreground color: #029cfd, background color: #f6f9fc, font size: 10.5pt (14px), font weight: normal). Expected contrast ratio of 4.5:1'
63
+ }
64
+ ]
65
+ }
66
+ ];
67
+ describe('afterEach', ()=>{
68
+ beforeEach(()=>{
69
+ vi.mocked(getIsVitestRunning).mockReturnValue(false);
70
+ vi.mocked(getIsVitestStandaloneRun).mockReturnValue(true);
71
+ });
72
+ const createContext = (overrides = {})=>({
73
+ viewMode: 'story',
74
+ reporting: {
75
+ reports: [],
76
+ addReport: vi.fn()
77
+ },
78
+ parameters: {
79
+ a11y: {
80
+ test: 'error'
81
+ }
82
+ },
83
+ globals: {
84
+ a11y: {}
85
+ },
86
+ ...overrides
87
+ });
88
+ it('should run accessibility checks and report results', async ()=>{
89
+ const context = createContext();
90
+ const result = {
91
+ violations
92
+ };
93
+ mockedRun.mockResolvedValue(result);
94
+ await expect(()=>afterEach(context)).rejects.toThrow();
95
+ expect(mockedRun).toHaveBeenCalledWith(context.parameters.a11y, context.id);
96
+ expect(context.reporting.addReport).toHaveBeenCalledWith({
97
+ type: 'a11y',
98
+ version: 1,
99
+ result,
100
+ status: 'failed'
101
+ });
102
+ });
103
+ it('should run accessibility checks and report results without throwing', async ()=>{
104
+ const context = createContext();
105
+ const result = {
106
+ violations
107
+ };
108
+ mockedRun.mockResolvedValue(result);
109
+ mocks.getIsVitestStandaloneRun.mockReturnValue(false);
110
+ await afterEach(context);
111
+ expect(mockedRun).toHaveBeenCalledWith(context.parameters.a11y, context.id);
112
+ expect(context.reporting.addReport).toHaveBeenCalledWith({
113
+ type: 'a11y',
114
+ version: 1,
115
+ result,
116
+ status: 'failed'
117
+ });
118
+ });
119
+ it('should run accessibility checks and should report them as warnings', async ()=>{
120
+ const context = createContext({
121
+ parameters: {
122
+ a11y: {
123
+ test: 'todo'
124
+ }
125
+ }
126
+ });
127
+ const result = {
128
+ violations
129
+ };
130
+ mockedRun.mockResolvedValue(result);
131
+ mocks.getIsVitestStandaloneRun.mockReturnValue(false);
132
+ await afterEach(context);
133
+ expect(mockedRun).toHaveBeenCalledWith(context.parameters.a11y, context.id);
134
+ expect(context.reporting.addReport).toHaveBeenCalledWith({
135
+ type: 'a11y',
136
+ version: 1,
137
+ result,
138
+ status: 'warning'
139
+ });
140
+ });
141
+ it('should report passed status when there are no violations', async ()=>{
142
+ const context = createContext();
143
+ const result = {
144
+ violations: []
145
+ };
146
+ mockedRun.mockResolvedValue(result);
147
+ await afterEach(context);
148
+ expect(mockedRun).toHaveBeenCalledWith(context.parameters.a11y, context.id);
149
+ expect(context.reporting.addReport).toHaveBeenCalledWith({
150
+ type: 'a11y',
151
+ version: 1,
152
+ result,
153
+ status: 'passed'
154
+ });
155
+ });
156
+ it('should not run accessibility checks when disable is true', async ()=>{
157
+ const context = createContext({
158
+ parameters: {
159
+ a11y: {
160
+ disable: true
161
+ }
162
+ }
163
+ });
164
+ await afterEach(context);
165
+ expect(mockedRun).not.toHaveBeenCalled();
166
+ expect(context.reporting.addReport).not.toHaveBeenCalled();
167
+ });
168
+ it('should not run accessibility checks when globals manual is true', async ()=>{
169
+ const context = createContext({
170
+ globals: {
171
+ a11y: {
172
+ manual: true
173
+ }
174
+ }
175
+ });
176
+ await afterEach(context);
177
+ expect(mockedRun).not.toHaveBeenCalled();
178
+ expect(context.reporting.addReport).not.toHaveBeenCalled();
179
+ });
180
+ it('should not run accessibility checks when parameters.a11y.test is "off"', async ()=>{
181
+ const context = createContext({
182
+ parameters: {
183
+ a11y: {
184
+ test: 'off'
185
+ }
186
+ }
187
+ });
188
+ await afterEach(context);
189
+ expect(mockedRun).not.toHaveBeenCalled();
190
+ expect(context.reporting.addReport).not.toHaveBeenCalled();
191
+ });
192
+ it('should report error when run throws an error', async ()=>{
193
+ const context = createContext();
194
+ const error = new Error('Test error');
195
+ mockedRun.mockRejectedValue(error);
196
+ await expect(()=>afterEach(context)).rejects.toThrow();
197
+ expect(mockedRun).toHaveBeenCalledWith(context.parameters.a11y, context.id);
198
+ expect(context.reporting.addReport).toHaveBeenCalledWith({
199
+ type: 'a11y',
200
+ version: 1,
201
+ result: {
202
+ error
203
+ },
204
+ status: 'failed'
205
+ });
206
+ });
207
+ it('should not run in docs mode', async ()=>{
208
+ const context = createContext({
209
+ viewMode: 'docs'
210
+ });
211
+ await afterEach(context);
212
+ expect(mockedRun).not.toHaveBeenCalled();
213
+ expect(context.reporting.addReport).not.toHaveBeenCalled();
214
+ });
215
+ });