test(refactor): Provide SVG selection in jsdomIt function

This commit is contained in:
quilicicf
2025-06-22 13:45:24 +02:00
parent 4145879003
commit 28840ebd84
2 changed files with 59 additions and 66 deletions

View File

@@ -1,27 +1,23 @@
import { addSVGa11yTitleDescription, setA11yDiagramInfo } from './accessibility.js';
import { ensureNodeFromSelector, jsdomIt } from './tests/util.js';
import { select } from 'd3';
import { expect } from 'vitest';
describe('accessibility', () => {
describe('setA11yDiagramInfo', () => {
jsdomIt('should set svg element role to "graphics-document document"', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
setA11yDiagramInfo(svgSelection, 'flowchart');
jsdomIt('should set svg element role to "graphics-document document"', ({ svg }) => {
setA11yDiagramInfo(svg, 'flowchart');
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('role')).toBe('graphics-document document');
});
jsdomIt('should set aria-roledescription to the diagram type', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
setA11yDiagramInfo(svgSelection, 'flowchart');
jsdomIt('should set aria-roledescription to the diagram type', ({ svg }) => {
setA11yDiagramInfo(svg, 'flowchart');
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('aria-roledescription')).toBe('flowchart');
});
jsdomIt('should not set aria-roledescription if the diagram type is empty', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
setA11yDiagramInfo(svgSelection, '');
jsdomIt('should not set aria-roledescription if the diagram type is empty', ({ svg }) => {
setA11yDiagramInfo(svg, '');
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('aria-roledescription')).toBeNull();
});
@@ -46,25 +42,25 @@ describe('accessibility', () => {
describe('with a11y description', () => {
const a11yDesc = 'a11y description';
jsdomIt('should set aria-labelledby to the title id inserted as a child', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
jsdomIt('should set aria-labelledby to the title id inserted as a child', ({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('aria-labelledby')).toBe(`chart-title-${givenId}`);
});
jsdomIt('should set aria-describedby to the description id inserted as a child', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('aria-describedby')).toBe(`chart-desc-${givenId}`);
});
jsdomIt(
'should set aria-describedby to the description id inserted as a child',
({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('aria-describedby')).toBe(`chart-desc-${givenId}`);
}
);
jsdomIt(
'should insert title tag as the first child with the text set to the accTitle given',
() => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
const titleNode = ensureNodeFromSelector('title', svgNode);
expect(titleNode?.innerHTML).toBe(a11yTitle);
@@ -73,9 +69,8 @@ describe('accessibility', () => {
jsdomIt(
'should insert desc tag as the 2nd child with the text set to accDescription given',
() => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
const descNode = ensureNodeFromSelector('desc', svgNode);
expect(descNode?.innerHTML).toBe(a11yDesc);
@@ -86,34 +81,30 @@ describe('accessibility', () => {
describe(`without a11y description`, {}, () => {
const a11yDesc = undefined;
jsdomIt('should set aria-labelledby to the title id inserted as a child', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
jsdomIt('should set aria-labelledby to the title id inserted as a child', ({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('aria-labelledby')).toBe(`chart-title-${givenId}`);
});
jsdomIt('should not set aria-describedby', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
jsdomIt('should not set aria-describedby', ({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('aria-describedby')).toBeNull();
});
jsdomIt(
'should insert title tag as the first child with the text set to the accTitle given',
() => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
const titleNode = ensureNodeFromSelector('title', svgNode);
expect(titleNode?.innerHTML).toBe(a11yTitle);
}
);
jsdomIt('should not insert description tag', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
jsdomIt('should not insert description tag', ({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
const descNode = svgNode.querySelector('desc');
expect(descNode).toBeNull();
@@ -127,33 +118,32 @@ describe('accessibility', () => {
describe('with a11y description', () => {
const a11yDesc = 'a11y description';
jsdomIt('should not set aria-labelledby', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
jsdomIt('should not set aria-labelledby', ({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('aria-labelledby')).toBeNull();
});
jsdomIt('should not insert title tag', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
jsdomIt('should not insert title tag', ({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
const titleNode = svgNode.querySelector('title');
expect(titleNode).toBeNull();
});
jsdomIt('should set aria-describedby to the description id inserted as a child', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('aria-describedby')).toBe(`chart-desc-${givenId}`);
});
jsdomIt(
'should set aria-describedby to the description id inserted as a child',
({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('aria-describedby')).toBe(`chart-desc-${givenId}`);
}
);
jsdomIt(
'should insert desc tag as the 2nd child with the text set to accDescription given',
() => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
const descNode = ensureNodeFromSelector('desc', svgNode);
expect(descNode?.innerHTML).toBe(a11yDesc);
@@ -164,31 +154,27 @@ describe('accessibility', () => {
describe('without a11y description', () => {
const a11yDesc = undefined;
jsdomIt('should not set aria-labelledby', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
jsdomIt('should not set aria-labelledby', ({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('aria-labelledby')).toBeNull();
});
jsdomIt('should not set aria-describedby', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
jsdomIt('should not set aria-describedby', ({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
expect(svgNode.getAttribute('aria-describedby')).toBeNull();
});
jsdomIt('should not insert title tag', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
jsdomIt('should not insert title tag', ({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
const titleNode = svgNode.querySelector('title');
expect(titleNode).toBeNull();
});
jsdomIt('should not insert description tag', () => {
const svgSelection = select<SVGSVGElement, never>('svg');
addSVGa11yTitleDescription(svgSelection, a11yTitle, a11yDesc, givenId);
jsdomIt('should not insert description tag', ({ svg }) => {
addSVGa11yTitleDescription(svg, a11yTitle, a11yDesc, givenId);
const svgNode = ensureNodeFromSelector('svg');
const descNode = svgNode.querySelector('desc');
expect(descNode).toBeNull();

View File

@@ -28,6 +28,7 @@ ${'2w'} | ${dayjs.duration(2, 'w')}
import { JSDOM } from 'jsdom';
import { expect, it } from 'vitest';
import { select, type Selection } from 'd3';
export const convert = (template: TemplateStringsArray, ...params: unknown[]) => {
const header = template[0]
@@ -61,6 +62,11 @@ export const MOCKED_BBOX = {
height: 666,
};
interface JsdomItInput {
// eslint-disable-next-line
svg: Selection<SVGSVGElement, never, HTMLElement, any>; // The `any` here comes from D3'as API.
}
/**
* Test method borrowed from d3 : https://github.com/d3/d3-selection/blob/v3.0.0/test/jsdom.js
*
@@ -74,7 +80,7 @@ export const MOCKED_BBOX = {
*
* This makes it possible to make structural tests instead of mocking everything.
*/
export function jsdomIt(message: string, run: () => void | Promise<void>) {
export function jsdomIt(message: string, run: (input: JsdomItInput) => void | Promise<void>) {
return it(message, async (): Promise<void> => {
const oldWindow = global.window;
const oldDocument = global.document;
@@ -99,7 +105,8 @@ export function jsdomIt(message: string, run: () => void | Promise<void>) {
setOnProtectedConstant(global, 'document', dom.window.document); // Fool D3 into thinking it's in a browser
setOnProtectedConstant(global, 'MutationObserver', undefined); // JSDOM doesn't like cytoscape elements
await run();
const svgSelection = select<SVGSVGElement, never>('svg');
await run({ svg: svgSelection });
} finally {
setOnProtectedConstant(global, 'window', oldWindow);
setOnProtectedConstant(global, 'document', oldDocument);