@afixt/test-utils 1.1.5 → 1.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afixt/test-utils",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "description": "Various utilities for accessibility testing",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -336,6 +336,50 @@ function getAccessibleName(element) {
336
336
  // So we don't return false here - let it fall through
337
337
  }
338
338
 
339
+ // STEP 11-4: meter element (native or role="meter")
340
+ // Per Axe aria-meter-name rule, meter elements need accessible name from
341
+ // aria-labelledby, aria-label (handled above), title, or associated label
342
+ // Text content inside meter is NOT a valid accessible name (it's fallback content)
343
+ // STEP 11-4.1: use title attribute
344
+ // STEP 11-4.2: for native meter, use associated label
345
+ // STEP 11-4.3: return false (don't use text content)
346
+ if (element.tagName.toLowerCase() === "meter" || element.getAttribute("role") === "meter") {
347
+ if (element.hasAttribute("title")) {
348
+ const titleValue = element.getAttribute("title");
349
+ if (strlen(titleValue) > 0) {
350
+ return titleValue;
351
+ }
352
+ }
353
+
354
+ // For native meter elements, check for associated label
355
+ if (element.tagName.toLowerCase() === "meter") {
356
+ // Check for label with for attribute
357
+ if (element.id) {
358
+ const label = document.querySelector('label[for="' + element.id + '"]');
359
+ if (label && strlen(getAccessibleText(label)) > 0) {
360
+ return getAccessibleText(label);
361
+ }
362
+ }
363
+
364
+ // Check for wrapping label
365
+ const parentLabel = element.closest("label");
366
+ if (parentLabel) {
367
+ // Get label text excluding the meter's own content
368
+ const clone = parentLabel.cloneNode(true);
369
+ const meterInClone = clone.querySelector("meter");
370
+ if (meterInClone) {
371
+ meterInClone.remove();
372
+ }
373
+ if (strlen(clone.textContent) > 0) {
374
+ return clone.textContent.trim();
375
+ }
376
+ }
377
+ }
378
+
379
+ // Meter text content is not an accessible name, return false
380
+ return false;
381
+ }
382
+
339
383
  // STEP 12: table element
340
384
  // STEP 12.1: caption element
341
385
  // STEP 12.2: use the title attribute
@@ -322,4 +322,46 @@ describe('getAccessibleName', () => {
322
322
  const obj = document.querySelector('object');
323
323
  expect(getAccessibleName(obj)).toBe(false);
324
324
  });
325
+
326
+ it('should handle ARIA meter with aria-label', () => {
327
+ document.body.innerHTML = `<div role="meter" aria-label="Disk usage" aria-valuenow="75"></div>`;
328
+ const meter = document.querySelector('[role="meter"]');
329
+ expect(getAccessibleName(meter)).toBe('Disk usage');
330
+ });
331
+
332
+ it('should handle ARIA meter with title attribute', () => {
333
+ document.body.innerHTML = `<div role="meter" title="Battery level" aria-valuenow="50"></div>`;
334
+ const meter = document.querySelector('[role="meter"]');
335
+ expect(getAccessibleName(meter)).toBe('Battery level');
336
+ });
337
+
338
+ it('should handle native meter with associated label', () => {
339
+ document.body.innerHTML = `<label for="cpu">CPU usage</label><meter id="cpu" value="0.6">60%</meter>`;
340
+ const meter = document.querySelector('meter');
341
+ expect(getAccessibleName(meter)).toBe('CPU usage');
342
+ });
343
+
344
+ it('should handle native meter wrapped in label', () => {
345
+ document.body.innerHTML = `<label>Memory: <meter value="0.8">80%</meter></label>`;
346
+ const meter = document.querySelector('meter');
347
+ expect(getAccessibleName(meter)).toBe('Memory:');
348
+ });
349
+
350
+ it('should return false for meter without accessible name', () => {
351
+ document.body.innerHTML = `<div role="meter" aria-valuenow="50">50%</div>`;
352
+ const meter = document.querySelector('[role="meter"]');
353
+ expect(getAccessibleName(meter)).toBe(false);
354
+ });
355
+
356
+ it('should return false for native meter without label', () => {
357
+ document.body.innerHTML = `<meter value="0.5">50%</meter>`;
358
+ const meter = document.querySelector('meter');
359
+ expect(getAccessibleName(meter)).toBe(false);
360
+ });
361
+
362
+ it('should handle meter with aria-labelledby', () => {
363
+ document.body.innerHTML = `<span id="signal-label">Signal strength</span><div role="meter" aria-labelledby="signal-label" aria-valuenow="4"></div>`;
364
+ const meter = document.querySelector('[role="meter"]');
365
+ expect(getAccessibleName(meter)).toBe('Signal strength');
366
+ });
325
367
  });