modified the sanitizeForSerialization method to remove unnecessary re… (#7950)

modified the sanitizeForSerialization method to remove unnecessary recursion, update e2e test to CORRECTLY test the functionality
This commit is contained in:
Jamie V. 2024-12-09 12:34:07 -08:00 committed by GitHub
parent d74e1b19b6
commit 5be103ea72
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 39 additions and 52 deletions

View File

@ -599,46 +599,33 @@ test.describe('Display Layout', () => {
// Verify filtering is working correctly // Verify filtering is working correctly
// Create a promise that resolves when we've seen enough new rows added // Check that no filtered values appear for at least 2 seconds
const rowsMutationPromise = page.evaluate(() => { const VERIFICATION_TIME = 2000; // 2 seconds
return new Promise((resolve) => { const CHECK_INTERVAL = 100; // Check every 100ms
const targetTable = document.querySelector(
'table[aria-label="Table Filter Off Value table content"]'
);
const config = { childList: true, subtree: true };
let changeCount = 0;
const requiredChanges = 20; // Number of changes to wait for
const observer = new MutationObserver((mutations) => { // Create a promise that will check for filtered values periodically
mutations.forEach((mutation) => { const checkForCorrectValues = new Promise((resolve, reject) => {
if (mutation.type === 'childList') { const interval = setInterval(async () => {
// Count added nodes const offCount = await tableFilterOn.locator('td[title="OFF"]').count();
changeCount += mutation.addedNodes.length; const onCount = await tableFilterOff.locator('td[title="ON"]').count();
} if (offCount > 0 || onCount > 0) {
}); clearInterval(interval);
reject(
new Error(
`Found ${offCount} OFF and ${onCount} ON values when expecting 0 OFF and 0 ON`
)
);
}
}, CHECK_INTERVAL);
// Check if the required number of changes has been met // After VERIFICATION_TIME, if no filtered values were found, resolve successfully
if (changeCount >= requiredChanges) { setTimeout(() => {
observer.disconnect(); // Disconnect observer after the required changes clearInterval(interval);
resolve(); resolve();
} }, VERIFICATION_TIME);
});
observer.observe(targetTable, config);
});
}); });
await rowsMutationPromise; await expect(checkForCorrectValues).resolves.toBeUndefined();
// Check ON table doesn't have any OFF values
await expect(tableFilterOn.locator('td[title="OFF"]')).toHaveCount(0);
const onCount = await tableFilterOn.locator('td[title="ON"]').count();
await expect(onCount).toBeGreaterThan(0);
// Check OFF table doesn't have any ON values
await expect(tableFilterOff.locator('td[title="ON"]')).toHaveCount(0);
const offCount = await tableFilterOff.locator('td[title="OFF"]').count();
await expect(offCount).toBeGreaterThan(0);
}); });
}); });

View File

@ -254,12 +254,6 @@ export default class TelemetryAPI {
* Sanitizes objects for consistent serialization by: * Sanitizes objects for consistent serialization by:
* 1. Removing non-plain objects (class instances) and functions * 1. Removing non-plain objects (class instances) and functions
* 2. Sorting object keys alphabetically to ensure consistent ordering * 2. Sorting object keys alphabetically to ensure consistent ordering
* 3. Recursively processing nested objects
*
* Note: When used as a JSON.stringify replacer, this function will process objects
* twice - once for the initial sorting and again when JSON.stringify processes the
* sorted result. This is acceptable for small options objects, which is the
* intended use case.
*/ */
sanitizeForSerialization(key, value) { sanitizeForSerialization(key, value) {
// Handle null and primitives directly // Handle null and primitives directly
@ -267,21 +261,27 @@ export default class TelemetryAPI {
return value; return value;
} }
// Remove functions and non-plain objects by returning undefined // Remove functions and non-plain objects (except arrays)
if (typeof value === 'function' || Object.getPrototypeOf(value) !== Object.prototype) { if (
typeof value === 'function' ||
(Object.getPrototypeOf(value) !== Object.prototype && !Array.isArray(value))
) {
return undefined; return undefined;
} }
// Handle plain objects // For plain objects, just sort the keys
const sortedObject = {}; if (!Array.isArray(value)) {
const keys = Object.keys(value).sort(); const sortedObject = {};
for (const objectKey of keys) { const sortedKeys = Object.keys(value).sort();
const itemValue = value[objectKey];
const sanitizedValue = this.sanitizeForSerialization(objectKey, itemValue); sortedKeys.forEach((objectKey) => {
sortedObject[objectKey] = sanitizedValue; sortedObject[objectKey] = value[objectKey];
});
return sortedObject;
} }
return sortedObject; return value;
} }
/** /**