Skip to content

Commit 55052a4

Browse files
committed
test: add a11y tests for new filter/table components
1 parent 686182e commit 55052a4

1 file changed

Lines changed: 280 additions & 0 deletions

File tree

test/nuxt/components.spec.ts

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ import PackageAccessControls from '~/components/PackageAccessControls.vue'
8282
import OrgMembersPanel from '~/components/OrgMembersPanel.vue'
8383
import OrgTeamsPanel from '~/components/OrgTeamsPanel.vue'
8484
import CodeMobileTreeDrawer from '~/components/CodeMobileTreeDrawer.vue'
85+
import ColumnPicker from '~/components/ColumnPicker.vue'
86+
import FilterChips from '~/components/FilterChips.vue'
87+
import FilterPanel from '~/components/FilterPanel.vue'
88+
import PackageListToolbar from '~/components/PackageListToolbar.vue'
89+
import PackageTable from '~/components/PackageTable.vue'
90+
import PackageTableRow from '~/components/PackageTableRow.vue'
91+
import PaginationControls from '~/components/PaginationControls.vue'
92+
import ViewModeToggle from '~/components/ViewModeToggle.vue'
8593

8694
describe('component accessibility audits', () => {
8795
describe('DateTime', () => {
@@ -891,4 +899,276 @@ describe('component accessibility audits', () => {
891899
expect(results.violations).toEqual([])
892900
})
893901
})
902+
903+
describe('ColumnPicker', () => {
904+
const mockColumns = [
905+
{ id: 'name', label: 'Name', visible: true, sortable: true },
906+
{ id: 'version', label: 'Version', visible: true, sortable: false },
907+
{ id: 'downloads', label: 'Downloads', visible: false, sortable: true },
908+
]
909+
910+
it('should have no accessibility violations', async () => {
911+
const component = await mountSuspended(ColumnPicker, {
912+
props: { columns: mockColumns },
913+
})
914+
const results = await runAxe(component)
915+
expect(results.violations).toEqual([])
916+
})
917+
})
918+
919+
describe('FilterChips', () => {
920+
it('should have no accessibility violations with chips', async () => {
921+
const chips = [
922+
{ id: 'text', type: 'text', label: 'Search', value: 'react' },
923+
{ id: 'keyword', type: 'keyword', label: 'Keyword', value: 'hooks' },
924+
]
925+
const component = await mountSuspended(FilterChips, {
926+
props: { chips },
927+
})
928+
const results = await runAxe(component)
929+
expect(results.violations).toEqual([])
930+
})
931+
932+
it('should have no accessibility violations with empty chips', async () => {
933+
const component = await mountSuspended(FilterChips, {
934+
props: { chips: [] },
935+
})
936+
const results = await runAxe(component)
937+
expect(results.violations).toEqual([])
938+
})
939+
})
940+
941+
describe('FilterPanel', () => {
942+
const defaultFilters = {
943+
text: '',
944+
searchScope: 'name' as const,
945+
downloadRange: 'any' as const,
946+
updatedWithin: 'any' as const,
947+
security: 'all' as const,
948+
keywords: [],
949+
}
950+
951+
it('should have no accessibility violations (collapsed)', async () => {
952+
const component = await mountSuspended(FilterPanel, {
953+
props: { filters: defaultFilters },
954+
})
955+
const results = await runAxe(component)
956+
expect(results.violations).toEqual([])
957+
})
958+
959+
it('should have no accessibility violations with active filters', async () => {
960+
const component = await mountSuspended(FilterPanel, {
961+
props: {
962+
filters: {
963+
...defaultFilters,
964+
text: 'react',
965+
keywords: ['hooks'],
966+
},
967+
},
968+
})
969+
const results = await runAxe(component)
970+
expect(results.violations).toEqual([])
971+
})
972+
})
973+
974+
describe('PackageListToolbar', () => {
975+
const defaultFilters = {
976+
text: '',
977+
searchScope: 'name' as const,
978+
downloadRange: 'any' as const,
979+
updatedWithin: 'any' as const,
980+
security: 'all' as const,
981+
keywords: [],
982+
}
983+
984+
const mockColumns = [
985+
{ id: 'name', label: 'Name', visible: true, sortable: true },
986+
{ id: 'version', label: 'Version', visible: true, sortable: false },
987+
]
988+
989+
it('should have no accessibility violations', async () => {
990+
const component = await mountSuspended(PackageListToolbar, {
991+
props: {
992+
filters: defaultFilters,
993+
sortOption: 'downloads-week-desc',
994+
viewMode: 'cards',
995+
columns: mockColumns,
996+
paginationMode: 'infinite',
997+
pageSize: 20,
998+
totalCount: 100,
999+
filteredCount: 100,
1000+
activeFilters: [],
1001+
},
1002+
})
1003+
const results = await runAxe(component)
1004+
expect(results.violations).toEqual([])
1005+
})
1006+
})
1007+
1008+
describe('PackageTable', () => {
1009+
const mockResults = [
1010+
{
1011+
package: {
1012+
name: 'vue',
1013+
version: '3.5.0',
1014+
description: 'The progressive JavaScript framework',
1015+
date: '2024-01-15T00:00:00.000Z',
1016+
keywords: ['framework'],
1017+
links: {},
1018+
publisher: { username: 'yyx990803' },
1019+
},
1020+
score: { final: 0.9, detail: { quality: 0.9, popularity: 0.9, maintenance: 0.9 } },
1021+
searchScore: 100000,
1022+
},
1023+
]
1024+
1025+
const mockColumns = [
1026+
{ id: 'name', label: 'Name', visible: true, sortable: true },
1027+
{ id: 'version', label: 'Version', visible: true, sortable: false },
1028+
{ id: 'description', label: 'Description', visible: true, sortable: false },
1029+
{ id: 'downloads', label: 'Downloads', visible: true, sortable: true },
1030+
]
1031+
1032+
it('should have no accessibility violations', async () => {
1033+
const component = await mountSuspended(PackageTable, {
1034+
props: {
1035+
results: mockResults,
1036+
columns: mockColumns,
1037+
},
1038+
})
1039+
const results = await runAxe(component)
1040+
expect(results.violations).toEqual([])
1041+
})
1042+
1043+
it('should have no accessibility violations with empty results', async () => {
1044+
const component = await mountSuspended(PackageTable, {
1045+
props: {
1046+
results: [],
1047+
columns: mockColumns,
1048+
},
1049+
})
1050+
const results = await runAxe(component)
1051+
expect(results.violations).toEqual([])
1052+
})
1053+
1054+
it('should have no accessibility violations when loading', async () => {
1055+
const component = await mountSuspended(PackageTable, {
1056+
props: {
1057+
results: [],
1058+
columns: mockColumns,
1059+
isLoading: true,
1060+
},
1061+
})
1062+
const results = await runAxe(component)
1063+
expect(results.violations).toEqual([])
1064+
})
1065+
})
1066+
1067+
describe('PackageTableRow', () => {
1068+
const mockResult = {
1069+
package: {
1070+
name: 'lodash',
1071+
version: '4.17.21',
1072+
description: 'A modern JavaScript utility library',
1073+
date: '2024-01-01T00:00:00.000Z',
1074+
keywords: ['utility', 'modules'],
1075+
links: {},
1076+
publisher: { username: 'jdalton' },
1077+
maintainers: [{ username: 'jdalton', email: 'test@test.com' }],
1078+
},
1079+
downloads: { weekly: 50000000 },
1080+
updated: '2024-01-01T00:00:00.000Z',
1081+
score: { final: 0.95, detail: { quality: 0.95, popularity: 0.99, maintenance: 0.9 } },
1082+
searchScore: 99999,
1083+
}
1084+
1085+
const mockColumns = [
1086+
{ id: 'name', label: 'Name', visible: true, sortable: true },
1087+
{ id: 'version', label: 'Version', visible: true, sortable: false },
1088+
{ id: 'description', label: 'Description', visible: true, sortable: false },
1089+
]
1090+
1091+
it('should have no accessibility violations', async () => {
1092+
// PackageTableRow needs to be wrapped in a table structure
1093+
const component = await mountSuspended(PackageTableRow, {
1094+
props: {
1095+
result: mockResult,
1096+
columns: mockColumns,
1097+
},
1098+
global: {
1099+
stubs: {
1100+
// Wrap in proper table structure for accessibility
1101+
},
1102+
},
1103+
attachTo: (() => {
1104+
const table = document.createElement('table')
1105+
const tbody = document.createElement('tbody')
1106+
table.appendChild(tbody)
1107+
document.body.appendChild(table)
1108+
return tbody
1109+
})(),
1110+
})
1111+
const results = await runAxe(component)
1112+
expect(results.violations).toEqual([])
1113+
})
1114+
})
1115+
1116+
describe('PaginationControls', () => {
1117+
it('should have no accessibility violations in infinite mode', async () => {
1118+
const component = await mountSuspended(PaginationControls, {
1119+
props: {
1120+
mode: 'infinite',
1121+
pageSize: 20,
1122+
currentPage: 1,
1123+
totalItems: 100,
1124+
},
1125+
})
1126+
const results = await runAxe(component)
1127+
expect(results.violations).toEqual([])
1128+
})
1129+
1130+
it('should have no accessibility violations in paginated mode', async () => {
1131+
const component = await mountSuspended(PaginationControls, {
1132+
props: {
1133+
mode: 'paginated',
1134+
pageSize: 20,
1135+
currentPage: 1,
1136+
totalItems: 100,
1137+
},
1138+
})
1139+
const results = await runAxe(component)
1140+
expect(results.violations).toEqual([])
1141+
})
1142+
1143+
it('should have no accessibility violations with multiple pages', async () => {
1144+
const component = await mountSuspended(PaginationControls, {
1145+
props: {
1146+
mode: 'paginated',
1147+
pageSize: 10,
1148+
currentPage: 5,
1149+
totalItems: 200,
1150+
},
1151+
})
1152+
const results = await runAxe(component)
1153+
expect(results.violations).toEqual([])
1154+
})
1155+
})
1156+
1157+
describe('ViewModeToggle', () => {
1158+
it('should have no accessibility violations in cards mode', async () => {
1159+
const component = await mountSuspended(ViewModeToggle, {
1160+
props: { modelValue: 'cards' },
1161+
})
1162+
const results = await runAxe(component)
1163+
expect(results.violations).toEqual([])
1164+
})
1165+
1166+
it('should have no accessibility violations in table mode', async () => {
1167+
const component = await mountSuspended(ViewModeToggle, {
1168+
props: { modelValue: 'table' },
1169+
})
1170+
const results = await runAxe(component)
1171+
expect(results.violations).toEqual([])
1172+
})
1173+
})
8941174
})

0 commit comments

Comments
 (0)