Allow for color parameters to be slightly different

Many WPT tests are looking for exact equality in color channels for
things like interpolation and color space conversion. This CL adds
an epsilon tolerance to the tests.

color-computed-relative-color-expected.txt and
color-computed-color-function-expected.txt need to be updated because
failure messages have changed.

color-computed-color-mix-function-expected.txt goes from 255 PASS,
249 FAIL to 289 PASS, 185 FAIL with this CL. Remaining failures all
look like hue interpolation/premultipliation issues.

Bug: 1092638
Change-Id: Ic8646fd790b29e5bb8461453208c246c7531c639
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3997697
Reviewed-by: Juanmi Huertas <juanmihd@chromium.org>
Commit-Queue: Aaron Krajeski <aaronhk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1068573}
diff --git a/css/support/computed-testcommon.js b/css/support/computed-testcommon.js
index 3d1c718..e8d3a52 100644
--- a/css/support/computed-testcommon.js
+++ b/css/support/computed-testcommon.js
@@ -25,7 +25,10 @@
     if (Array.isArray(computed)) {
       assert_in_array(readValue, computed);
     } else {
-      assert_equals(readValue, computed);
+      if (property == "color")
+        colorValuesAlmostEqual(readValue, computed, 0.0001);
+      else
+        assert_equals(readValue, computed);
     }
     if (readValue !== specified) {
       target.style[property] = '';
@@ -36,6 +39,31 @@
   }, `Property ${property} value '${specified}'${titleExtra ? ' ' + titleExtra : ''}`);
 }
 
+function colorValuesAlmostEqual(color1, color2, epsilon) {
+  // Colors can be split by spaces, commas or the '(' character.
+  const colorElementDividers = /( |\(|,)/;
+  // Return the string stripped of numbers.
+  function getNonNumbers(color) {
+    return color.replace(/[0-9]/g, '');
+  }
+  // Return an array of all numbers in the color.
+  function getNumbers(color) {
+    const result = [];
+    // const entries = color.split(colorElementDividers);
+    color.split(colorElementDividers).forEach(element => {
+      const numberElement = parseFloat(element);
+      if (!isNaN(numberElement)) {
+        result.push(numberElement);
+      }
+    });
+    return result;
+  }
+
+  assert_array_approx_equals(getNumbers(color1), getNumbers(color2), epsilon, "Numeric parameters are approximately equal.");
+  // Assert that the text of the two colors are equal. i.e. colorSpace, colorFunction and format.
+  assert_equals(getNonNumbers(color1), getNonNumbers(color2), "Color format is correct.");
+}
+
 function testComputedValueGreaterOrLowerThan(property, specified, expected, titleExtra) {
     test(() => {
       const target = document.getElementById('target');