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+

});