@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.
- package/dist/AccessibilityRuleMaps.js +532 -0
- package/dist/a11yRunner.js +105 -0
- package/dist/a11yRunner.test.js +21 -0
- package/dist/a11yRunnerUtils.js +30 -0
- package/dist/a11yRunnerUtils.test.js +61 -0
- package/dist/{699.js → apcaChecker.js} +1 -255
- package/dist/apcaChecker.test.js +124 -0
- package/dist/axeRuleMappingHelper.js +4 -0
- package/dist/components/A11YPanel.js +140 -0
- package/dist/components/A11YPanel.stories.js +198 -0
- package/dist/components/A11YPanel.test.js +110 -0
- package/dist/components/A11yContext.js +438 -0
- package/dist/components/A11yContext.test.js +277 -0
- package/dist/components/Report/Details.js +169 -0
- package/dist/components/Report/Report.js +106 -0
- package/dist/components/Report/Report.stories.js +86 -0
- package/dist/components/Tabs.js +54 -0
- package/dist/components/TestDiscrepancyMessage.js +55 -0
- package/dist/components/TestDiscrepancyMessage.stories.js +40 -0
- package/dist/components/VisionSimulator.js +83 -0
- package/dist/components/VisionSimulator.stories.js +56 -0
- package/dist/constants.js +25 -0
- package/dist/index.js +5 -6
- package/dist/manager.js +11 -1540
- package/dist/manager.test.js +86 -0
- package/dist/params.js +0 -0
- package/dist/postinstall.js +1 -1
- package/dist/preview.js +68 -1
- package/dist/preview.test.js +215 -0
- package/dist/results.mock.js +874 -0
- package/dist/types.js +6 -0
- package/dist/utils.js +21 -0
- package/dist/{100.js → visionSimulatorFilters.js} +1 -23
- package/dist/withVisionSimulator.js +41 -0
- package/package.json +1 -1
- package/dist/212.js +0 -1965
- package/dist/212.js.LICENSE.txt +0 -19
- package/dist/rslib-runtime.js +0 -37
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { ManagerContext } from "storybook/manager-api";
|
|
3
|
+
import { expect, fn, userEvent, waitFor, within } from "storybook/test";
|
|
4
|
+
import { styled } from "storybook/theming";
|
|
5
|
+
import preview from "../../../../.storybook/preview";
|
|
6
|
+
import { results } from "../results.mock.js";
|
|
7
|
+
import { RuleType } from "../types.js";
|
|
8
|
+
import { A11YPanel } from "./A11YPanel.js";
|
|
9
|
+
import { A11yContext } from "./A11yContext.js";
|
|
10
|
+
const emptyResults = {
|
|
11
|
+
passes: [],
|
|
12
|
+
incomplete: [],
|
|
13
|
+
violations: [],
|
|
14
|
+
toolOptions: {},
|
|
15
|
+
inapplicable: [],
|
|
16
|
+
testEngine: {
|
|
17
|
+
name: '',
|
|
18
|
+
version: ''
|
|
19
|
+
},
|
|
20
|
+
testRunner: {
|
|
21
|
+
name: ''
|
|
22
|
+
},
|
|
23
|
+
testEnvironment: {
|
|
24
|
+
userAgent: '',
|
|
25
|
+
windowWidth: 0,
|
|
26
|
+
windowHeight: 0
|
|
27
|
+
},
|
|
28
|
+
url: '',
|
|
29
|
+
timestamp: ''
|
|
30
|
+
};
|
|
31
|
+
const StyledWrapper = styled.div(({ theme })=>({
|
|
32
|
+
backgroundColor: theme.background.content,
|
|
33
|
+
fontSize: theme.typography.size.s2 - 1,
|
|
34
|
+
color: theme.color.defaultText,
|
|
35
|
+
display: 'block',
|
|
36
|
+
height: '100%',
|
|
37
|
+
position: 'absolute',
|
|
38
|
+
left: 0,
|
|
39
|
+
right: 0,
|
|
40
|
+
bottom: 0,
|
|
41
|
+
overflow: 'auto'
|
|
42
|
+
}));
|
|
43
|
+
const managerContext = {
|
|
44
|
+
state: {},
|
|
45
|
+
api: {
|
|
46
|
+
getDocsUrl: fn().mockName('api::getDocsUrl'),
|
|
47
|
+
getCurrentParameter: fn().mockName('api::getCurrentParameter')
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const meta = preview.meta({
|
|
51
|
+
title: 'Panel',
|
|
52
|
+
component: A11YPanel,
|
|
53
|
+
parameters: {
|
|
54
|
+
layout: 'fullscreen'
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
const context = {
|
|
58
|
+
parameters: {},
|
|
59
|
+
handleManual: fn(),
|
|
60
|
+
highlighted: false,
|
|
61
|
+
toggleHighlight: fn(),
|
|
62
|
+
tab: RuleType.VIOLATION,
|
|
63
|
+
setTab: fn(),
|
|
64
|
+
setStatus: fn(),
|
|
65
|
+
handleCopyLink: fn(),
|
|
66
|
+
toggleOpen: fn(),
|
|
67
|
+
allExpanded: false,
|
|
68
|
+
handleCollapseAll: fn(),
|
|
69
|
+
handleExpandAll: fn(),
|
|
70
|
+
handleSelectionChange: fn(),
|
|
71
|
+
handleJumpToElement: fn()
|
|
72
|
+
};
|
|
73
|
+
const Template = (args)=>/*#__PURE__*/ react.createElement(A11yContext.Provider, {
|
|
74
|
+
value: {
|
|
75
|
+
...context,
|
|
76
|
+
...args
|
|
77
|
+
}
|
|
78
|
+
}, /*#__PURE__*/ react.createElement(ManagerContext.Provider, {
|
|
79
|
+
value: managerContext
|
|
80
|
+
}, /*#__PURE__*/ react.createElement(StyledWrapper, {
|
|
81
|
+
id: "panel-tab-content"
|
|
82
|
+
}, /*#__PURE__*/ react.createElement(A11YPanel, null))));
|
|
83
|
+
const Initializing = meta.story({
|
|
84
|
+
render: ()=>/*#__PURE__*/ react.createElement(Template, {
|
|
85
|
+
results: emptyResults,
|
|
86
|
+
status: "initial",
|
|
87
|
+
error: null,
|
|
88
|
+
discrepancy: null,
|
|
89
|
+
selectedItems: new Map()
|
|
90
|
+
})
|
|
91
|
+
});
|
|
92
|
+
const Disabled = meta.story({
|
|
93
|
+
render: ()=>/*#__PURE__*/ react.createElement(Template, {
|
|
94
|
+
results: emptyResults,
|
|
95
|
+
status: "initial",
|
|
96
|
+
error: null,
|
|
97
|
+
discrepancy: null,
|
|
98
|
+
selectedItems: new Map(),
|
|
99
|
+
parameters: {
|
|
100
|
+
disable: true
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
});
|
|
104
|
+
const Manual = meta.story({
|
|
105
|
+
render: ()=>/*#__PURE__*/ react.createElement(Template, {
|
|
106
|
+
results: emptyResults,
|
|
107
|
+
status: "manual",
|
|
108
|
+
error: null,
|
|
109
|
+
discrepancy: null,
|
|
110
|
+
selectedItems: new Map()
|
|
111
|
+
})
|
|
112
|
+
});
|
|
113
|
+
const ManualWithDiscrepancy = meta.story({
|
|
114
|
+
render: ()=>/*#__PURE__*/ react.createElement(Template, {
|
|
115
|
+
results: emptyResults,
|
|
116
|
+
status: "manual",
|
|
117
|
+
error: null,
|
|
118
|
+
discrepancy: 'cliFailedButModeManual',
|
|
119
|
+
selectedItems: new Map()
|
|
120
|
+
})
|
|
121
|
+
});
|
|
122
|
+
const Running = meta.story({
|
|
123
|
+
render: ()=>/*#__PURE__*/ react.createElement(Template, {
|
|
124
|
+
results: emptyResults,
|
|
125
|
+
status: "running",
|
|
126
|
+
error: null,
|
|
127
|
+
discrepancy: null,
|
|
128
|
+
selectedItems: new Map()
|
|
129
|
+
})
|
|
130
|
+
});
|
|
131
|
+
const ReadyWithResults = meta.story({
|
|
132
|
+
render: ()=>/*#__PURE__*/ react.createElement(Template, {
|
|
133
|
+
results: results,
|
|
134
|
+
status: "ready",
|
|
135
|
+
error: null,
|
|
136
|
+
discrepancy: null,
|
|
137
|
+
selectedItems: new Map([
|
|
138
|
+
[
|
|
139
|
+
`${RuleType.VIOLATION}.${results.violations["0"].id}`,
|
|
140
|
+
`${RuleType.VIOLATION}.${results.violations["0"].id}.1`
|
|
141
|
+
]
|
|
142
|
+
])
|
|
143
|
+
}),
|
|
144
|
+
play: async ({ canvasElement })=>{
|
|
145
|
+
const canvas = within(canvasElement);
|
|
146
|
+
const btn = await waitFor(()=>canvas.findByRole('button', {
|
|
147
|
+
name: /Rerun accessibility scan/
|
|
148
|
+
}), {
|
|
149
|
+
timeout: 3000
|
|
150
|
+
});
|
|
151
|
+
await userEvent.click(btn);
|
|
152
|
+
expect(context.handleManual).toHaveBeenCalled();
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
const ReadyWithResultsDiscrepancyCLIPassedBrowserFailed = meta.story({
|
|
156
|
+
render: ()=>/*#__PURE__*/ react.createElement(Template, {
|
|
157
|
+
results: results,
|
|
158
|
+
status: "ready",
|
|
159
|
+
error: null,
|
|
160
|
+
discrepancy: 'cliPassedBrowserFailed',
|
|
161
|
+
selectedItems: new Map([
|
|
162
|
+
[
|
|
163
|
+
`${RuleType.VIOLATION}.${results.violations["0"].id}`,
|
|
164
|
+
`${RuleType.VIOLATION}.${results.violations["0"].id}.1`
|
|
165
|
+
]
|
|
166
|
+
])
|
|
167
|
+
})
|
|
168
|
+
});
|
|
169
|
+
const Error = meta.story({
|
|
170
|
+
render: ()=>/*#__PURE__*/ react.createElement(Template, {
|
|
171
|
+
results: emptyResults,
|
|
172
|
+
status: "error",
|
|
173
|
+
error: 'TypeError: Configured rule { impact: "moderate", disable: true } is invalid. Rules must be an object with at least an id property.',
|
|
174
|
+
discrepancy: null,
|
|
175
|
+
selectedItems: new Map()
|
|
176
|
+
})
|
|
177
|
+
});
|
|
178
|
+
const ErrorStateWithObject = meta.story({
|
|
179
|
+
render: ()=>/*#__PURE__*/ react.createElement(Template, {
|
|
180
|
+
results: emptyResults,
|
|
181
|
+
status: "error",
|
|
182
|
+
error: {
|
|
183
|
+
message: 'Test error object message'
|
|
184
|
+
},
|
|
185
|
+
discrepancy: null,
|
|
186
|
+
selectedItems: new Map()
|
|
187
|
+
})
|
|
188
|
+
});
|
|
189
|
+
const Broken = meta.story({
|
|
190
|
+
render: ()=>/*#__PURE__*/ react.createElement(Template, {
|
|
191
|
+
results: emptyResults,
|
|
192
|
+
status: "component-test-error",
|
|
193
|
+
error: null,
|
|
194
|
+
discrepancy: null,
|
|
195
|
+
selectedItems: new Map()
|
|
196
|
+
})
|
|
197
|
+
});
|
|
198
|
+
export { Broken, Disabled, Error, ErrorStateWithObject, Initializing, Manual, ManualWithDiscrepancy, ReadyWithResults, ReadyWithResultsDiscrepancyCLIPassedBrowserFailed, Running };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { fireEvent, render } from "@testing-library/react";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import react from "react";
|
|
4
|
+
import { ThemeProvider, convert, themes } from "storybook/theming";
|
|
5
|
+
import { A11YPanel } from "./A11YPanel.js";
|
|
6
|
+
import { useA11yContext } from "./A11yContext.js";
|
|
7
|
+
import * as __rspack_external_storybook_manager_api_d834c1f5 from "storybook/manager-api";
|
|
8
|
+
vi.mock('storybook/manager-api');
|
|
9
|
+
const mockedManagerApi = vi.mocked(__rspack_external_storybook_manager_api_d834c1f5);
|
|
10
|
+
vi.mock('./A11yContext');
|
|
11
|
+
const mockedUseA11yContext = vi.mocked(useA11yContext);
|
|
12
|
+
mockedManagerApi.useParameter.mockReturnValue({
|
|
13
|
+
manual: false
|
|
14
|
+
});
|
|
15
|
+
const emptyResults = {
|
|
16
|
+
passes: [],
|
|
17
|
+
incomplete: [],
|
|
18
|
+
violations: [],
|
|
19
|
+
toolOptions: {},
|
|
20
|
+
inapplicable: [],
|
|
21
|
+
testEngine: {
|
|
22
|
+
name: '',
|
|
23
|
+
version: ''
|
|
24
|
+
},
|
|
25
|
+
testRunner: {
|
|
26
|
+
name: ''
|
|
27
|
+
},
|
|
28
|
+
testEnvironment: {
|
|
29
|
+
userAgent: '',
|
|
30
|
+
windowWidth: 0,
|
|
31
|
+
windowHeight: 0
|
|
32
|
+
},
|
|
33
|
+
url: '',
|
|
34
|
+
timestamp: ''
|
|
35
|
+
};
|
|
36
|
+
describe('A11YPanel', ()=>{
|
|
37
|
+
it('should render initializing state', ()=>{
|
|
38
|
+
mockedUseA11yContext.mockReturnValue({
|
|
39
|
+
parameters: {},
|
|
40
|
+
results: emptyResults,
|
|
41
|
+
status: 'initial',
|
|
42
|
+
handleManual: vi.fn(),
|
|
43
|
+
error: null
|
|
44
|
+
});
|
|
45
|
+
const element = render(/*#__PURE__*/ react.createElement(ThemeProvider, {
|
|
46
|
+
theme: convert(themes.light)
|
|
47
|
+
}, /*#__PURE__*/ react.createElement(A11YPanel, null)));
|
|
48
|
+
expect(element.getByText('Please wait while the addon is initializing...')).toBeInTheDocument();
|
|
49
|
+
});
|
|
50
|
+
it('should render manual state', ()=>{
|
|
51
|
+
const handleManual = vi.fn();
|
|
52
|
+
mockedUseA11yContext.mockReturnValue({
|
|
53
|
+
parameters: {},
|
|
54
|
+
results: emptyResults,
|
|
55
|
+
status: 'manual',
|
|
56
|
+
handleManual,
|
|
57
|
+
error: null
|
|
58
|
+
});
|
|
59
|
+
const component = render(/*#__PURE__*/ react.createElement(ThemeProvider, {
|
|
60
|
+
theme: convert(themes.light)
|
|
61
|
+
}, /*#__PURE__*/ react.createElement(A11YPanel, null)));
|
|
62
|
+
const runTestButton = component.getByText('Run accessibility scan');
|
|
63
|
+
expect(runTestButton).toBeInTheDocument();
|
|
64
|
+
fireEvent.click(runTestButton);
|
|
65
|
+
expect(handleManual).toHaveBeenCalled();
|
|
66
|
+
});
|
|
67
|
+
it('should render running state', ()=>{
|
|
68
|
+
mockedUseA11yContext.mockReturnValue({
|
|
69
|
+
parameters: {},
|
|
70
|
+
results: emptyResults,
|
|
71
|
+
status: 'running',
|
|
72
|
+
handleManual: vi.fn(),
|
|
73
|
+
error: null
|
|
74
|
+
});
|
|
75
|
+
const component = render(/*#__PURE__*/ react.createElement(ThemeProvider, {
|
|
76
|
+
theme: convert(themes.light)
|
|
77
|
+
}, /*#__PURE__*/ react.createElement(A11YPanel, null)));
|
|
78
|
+
expect(component.getByText('Please wait while the accessibility scan is running...')).toBeInTheDocument();
|
|
79
|
+
});
|
|
80
|
+
it('should render error state', ()=>{
|
|
81
|
+
mockedUseA11yContext.mockReturnValue({
|
|
82
|
+
parameters: {},
|
|
83
|
+
results: emptyResults,
|
|
84
|
+
status: 'error',
|
|
85
|
+
handleManual: vi.fn(),
|
|
86
|
+
error: 'Test error message'
|
|
87
|
+
});
|
|
88
|
+
const component = render(/*#__PURE__*/ react.createElement(ThemeProvider, {
|
|
89
|
+
theme: convert(themes.light)
|
|
90
|
+
}, /*#__PURE__*/ react.createElement(A11YPanel, null)));
|
|
91
|
+
expect(component.container).toHaveTextContent('The accessibility scan encountered an error');
|
|
92
|
+
expect(component.container).toHaveTextContent('Test error message');
|
|
93
|
+
});
|
|
94
|
+
it('should render error state with object error', ()=>{
|
|
95
|
+
mockedUseA11yContext.mockReturnValue({
|
|
96
|
+
parameters: {},
|
|
97
|
+
results: emptyResults,
|
|
98
|
+
status: 'error',
|
|
99
|
+
handleManual: vi.fn(),
|
|
100
|
+
error: {
|
|
101
|
+
message: 'Test error object message'
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
const component = render(/*#__PURE__*/ react.createElement(ThemeProvider, {
|
|
105
|
+
theme: convert(themes.light)
|
|
106
|
+
}, /*#__PURE__*/ react.createElement(A11YPanel, null)));
|
|
107
|
+
expect(component.container).toHaveTextContent('The accessibility scan encountered an error');
|
|
108
|
+
expect(component.container).toHaveTextContent('{ "message": "Test error object message" }');
|
|
109
|
+
});
|
|
110
|
+
});
|