Skip to content

Commit d98bc12

Browse files
Copilottsmarvin
andcommitted
refactor: improve performance and validation in accessibility tests and type guards
Co-authored-by: tsmarvin <[email protected]>
1 parent 637e0fe commit d98bc12

File tree

2 files changed

+37
-18
lines changed

2 files changed

+37
-18
lines changed

src/scripts/index.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,17 +1265,38 @@ const processedTimezoneCache = new Map<number, ProcessedTimezoneData>();
12651265
// Cache key for localStorage
12661266
const TIMEZONE_CACHE_KEY = 'everytimezone_processed_timezones';
12671267

1268+
/**
1269+
* Type guard to check if an object is a valid TimeZone
1270+
*/
1271+
function isValidTimeZone(obj: unknown): obj is TimeZone {
1272+
return (
1273+
typeof obj === 'object' &&
1274+
obj !== null &&
1275+
typeof (obj as TimeZone).name === 'string' &&
1276+
typeof (obj as TimeZone).offset === 'number' &&
1277+
typeof (obj as TimeZone).displayName === 'string' &&
1278+
typeof (obj as TimeZone).iana === 'string' &&
1279+
typeof (obj as TimeZone).cityName === 'string' &&
1280+
typeof (obj as TimeZone).abbreviation === 'string'
1281+
// Note: daylight, isCustom, isOffCycle, coordinates are optional properties
1282+
);
1283+
}
1284+
12681285
/**
12691286
* Type guard to check if an object is a valid ProcessedTimezoneData
12701287
*/
12711288
function isProcessedTimezoneData(obj: unknown): obj is ProcessedTimezoneData {
1289+
const candidate = obj as ProcessedTimezoneData;
12721290
return (
12731291
typeof obj === 'object' &&
12741292
obj !== null &&
1275-
Array.isArray((obj as ProcessedTimezoneData).juneTimeZones) &&
1276-
Array.isArray((obj as ProcessedTimezoneData).decemberTimeZones) &&
1277-
typeof (obj as ProcessedTimezoneData).userTimezone === 'string' &&
1278-
typeof (obj as ProcessedTimezoneData).currentYear === 'number'
1293+
Array.isArray(candidate.juneTimeZones) &&
1294+
Array.isArray(candidate.decemberTimeZones) &&
1295+
typeof candidate.userTimezone === 'string' &&
1296+
typeof candidate.currentYear === 'number' &&
1297+
// Validate that array contents are valid TimeZone objects to prevent runtime errors
1298+
candidate.juneTimeZones.every(isValidTimeZone) &&
1299+
candidate.decemberTimeZones.every(isValidTimeZone)
12791300
);
12801301
}
12811302

test/accessibility-comprehensive.test.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -293,15 +293,15 @@ describe('WCAG AAA Accessibility Standards', () => {
293293
it('should meet WCAG AAA color contrast requirements (7:1 for normal text)', () => {
294294
// Test all text elements for complete accessibility coverage
295295
const textElements = document.querySelectorAll('*');
296-
let contrastIssues: string[] = [];
297-
298-
textElements.forEach((element, index) => {
296+
297+
// Use functional approach for better performance instead of repeatedly calling push()
298+
const contrastIssues = Array.from(textElements).flatMap((element, index) => {
299299
const styles = window.getComputedStyle(element);
300300
const textColor = styles.color;
301301
const backgroundColor = getComputedBackgroundColor(element);
302302

303303
// Test all elements including hidden ones for screen reader compatibility
304-
if (!element.textContent?.trim()) return;
304+
if (!element.textContent?.trim()) return [];
305305

306306
if (textColor && backgroundColor) {
307307
const textRGB = parseColor(textColor);
@@ -311,12 +311,11 @@ describe('WCAG AAA Accessibility Standards', () => {
311311
const contrastRatio = getContrastRatio(textRGB, bgRGB);
312312
// WCAG AAA requires 7:1 for normal text (not 4.5:1 which is AA)
313313
if (contrastRatio < 7.0) {
314-
contrastIssues.push(
315-
`${element.tagName}[${index}] "${element.textContent?.trim().substring(0, 20)}..." contrast ratio ${contrastRatio.toFixed(2)}:1 is below WCAG AAA standard (7:1)`
316-
);
314+
return [`${element.tagName}[${index}] "${element.textContent?.trim().substring(0, 20)}..." contrast ratio ${contrastRatio.toFixed(2)}:1 is below WCAG AAA standard (7:1)`];
317315
}
318316
}
319317
}
318+
return [];
320319
});
321320

322321
expect(contrastIssues.length, `Contrast issues found at ${size.name}: ${contrastIssues.join(', ')}`).toBe(0);
@@ -325,15 +324,15 @@ describe('WCAG AAA Accessibility Standards', () => {
325324
it('should meet WCAG AAA large text contrast requirements (4.5:1)', () => {
326325
// Test all elements for complete accessibility coverage
327326
const allElements = document.querySelectorAll('*');
328-
let contrastIssues: string[] = [];
329-
330-
allElements.forEach((element, index) => {
327+
328+
// Use functional approach for better performance instead of repeatedly calling push()
329+
const contrastIssues = Array.from(allElements).flatMap((element, index) => {
331330
const styles = window.getComputedStyle(element);
332331
const fontSize = parseFloat(styles.fontSize);
333332
const fontWeight = styles.fontWeight;
334333

335334
// Test all elements including hidden ones for screen reader compatibility
336-
if (!element.textContent?.trim()) return;
335+
if (!element.textContent?.trim()) return [];
337336

338337
// Large text is 18pt+ (24px+) or 14pt+ (18.5px+) bold according to WCAG
339338
const isLargeText = fontSize >= 24 || (fontSize >= 18.5 && (fontWeight === 'bold' || parseInt(fontWeight) >= 700));
@@ -350,13 +349,12 @@ describe('WCAG AAA Accessibility Standards', () => {
350349
const contrastRatio = getContrastRatio(textRGB, bgRGB);
351350
// WCAG AAA requires 4.5:1 for large text
352351
if (contrastRatio < 4.5) {
353-
contrastIssues.push(
354-
`Large text ${element.tagName}[${index}] "${element.textContent?.trim().substring(0, 20)}..." contrast ratio ${contrastRatio.toFixed(2)}:1 is below WCAG AAA standard (4.5:1)`
355-
);
352+
return [`Large text ${element.tagName}[${index}] "${element.textContent?.trim().substring(0, 20)}..." contrast ratio ${contrastRatio.toFixed(2)}:1 is below WCAG AAA standard (4.5:1)`];
356353
}
357354
}
358355
}
359356
}
357+
return [];
360358
});
361359

362360
expect(contrastIssues.length, `Large text contrast issues at ${size.name}: ${contrastIssues.join(', ')}`).toBe(0);

0 commit comments

Comments
 (0)