feat(plugin-axe): add setup wizard binding · code-pushup/cli@5f2df75
1+import type { PluginAnswer } from '@code-pushup/models';
2+import { createMockTree } from '@code-pushup/test-utils';
3+import { axeSetupBinding as binding } from './binding.js';
4+5+const defaultAnswers: Record<string, PluginAnswer> = {
6+'axe.urls': 'http://localhost:4200',
7+'axe.preset': 'wcag21aa',
8+'axe.setupScript': false,
9+'axe.categories': true,
10+};
11+12+const noCategoryAnswers: Record<string, PluginAnswer> = {
13+ ...defaultAnswers,
14+'axe.categories': false,
15+};
16+17+describe('axeSetupBinding', () => {
18+describe('prompts', () => {
19+it('should offer preset choices with wcag21aa as default', async () => {
20+await expect(binding.prompts!()).resolves.toIncludeAllPartialMembers([
21+{ key: 'axe.preset', type: 'select', default: 'wcag21aa' },
22+]);
23+});
24+25+it('should default setupScript to false', async () => {
26+await expect(binding.prompts!()).resolves.toIncludeAllPartialMembers([
27+{ key: 'axe.setupScript', type: 'confirm', default: false },
28+]);
29+});
30+});
31+32+describe('generateConfig with categories selected', () => {
33+it('should declare plugin as a variable for use in category refs', async () => {
34+const { pluginDeclaration } = await binding.generateConfig(
35+defaultAnswers,
36+createMockTree(),
37+);
38+expect(pluginDeclaration).toStrictEqual({
39+identifier: 'axe',
40+expression: "axePlugin('http://localhost:4200')",
41+});
42+});
43+44+it('should import axeGroupRefs helper', async () => {
45+const { imports } = await binding.generateConfig(
46+defaultAnswers,
47+createMockTree(),
48+);
49+expect(imports).toStrictEqual([
50+expect.objectContaining({ namedImports: ['axeGroupRefs'] }),
51+]);
52+});
53+54+it('should produce accessibility category with refs expression', async () => {
55+const { categories } = await binding.generateConfig(
56+defaultAnswers,
57+createMockTree(),
58+);
59+expect(categories).toStrictEqual([
60+expect.objectContaining({
61+slug: 'a11y',
62+refsExpression: 'axeGroupRefs(axe)',
63+}),
64+]);
65+});
66+});
67+68+describe('generateConfig without categories selected', () => {
69+it('should not declare plugin as a variable', async () => {
70+const { pluginDeclaration } = await binding.generateConfig(
71+noCategoryAnswers,
72+createMockTree(),
73+);
74+expect(pluginDeclaration).toBeUndefined();
75+});
76+77+it('should not import axeGroupRefs helper', async () => {
78+const { imports } = await binding.generateConfig(
79+noCategoryAnswers,
80+createMockTree(),
81+);
82+expect(imports[0]).not.toHaveProperty('namedImports');
83+});
84+85+it('should not produce categories', async () => {
86+const { categories } = await binding.generateConfig(
87+noCategoryAnswers,
88+createMockTree(),
89+);
90+expect(categories).toBeUndefined();
91+});
92+});
93+94+describe('setup script', () => {
95+it('should write setup script file when confirmed', async () => {
96+const tree = createMockTree();
97+await binding.generateConfig(
98+{ ...defaultAnswers, 'axe.setupScript': true },
99+tree,
100+);
101+expect(tree.written.get('./axe-setup.ts')).toContain(
102+"import type { Page } from 'playwright-core'",
103+);
104+});
105+106+it('should include setupScript in plugin call when confirmed', async () => {
107+const { pluginDeclaration } = await binding.generateConfig(
108+{ ...defaultAnswers, 'axe.setupScript': true },
109+createMockTree(),
110+);
111+expect(pluginDeclaration!.expression).toContain(
112+"setupScript: './axe-setup.ts'",
113+);
114+});
115+116+it('should not write setup script file when declined', async () => {
117+const tree = createMockTree();
118+await binding.generateConfig(defaultAnswers, tree);
119+expect(tree.written.size).toBe(0);
120+});
121+});
122+123+it('should include non-default preset in plugin call', async () => {
124+const { pluginDeclaration } = await binding.generateConfig(
125+{ ...defaultAnswers, 'axe.preset': 'wcag22aa' },
126+createMockTree(),
127+);
128+expect(pluginDeclaration!.expression).toContain("preset: 'wcag22aa'");
129+});
130+131+it('should format multiple URLs as array', async () => {
132+const { pluginDeclaration } = await binding.generateConfig(
133+{
134+ ...defaultAnswers,
135+'axe.urls': 'http://localhost:4200/login, http://localhost:4200/home',
136+},
137+createMockTree(),
138+);
139+expect(pluginDeclaration!.expression).toContain(
140+"axePlugin(['http://localhost:4200/login', 'http://localhost:4200/home']",
141+);
142+});
143+});