This is an automated email from the ASF dual-hosted git repository.

jky pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flagon-useralejs.git


The following commit(s) were added to refs/heads/master by this push:
     new 4eec2ff  Moved attributes and CSS to main package
4eec2ff is described below

commit 4eec2ffd87880bc96858f2802b054058eeebb003
Author: Jason Young <jason_...@protonmail.com>
AuthorDate: Tue Aug 20 12:57:33 2024 -0700

    Moved attributes and CSS to main package
---
 build/UserALEWebExtension/background.js  | 43 +++++++++++++++
 build/UserALEWebExtension/content.js     | 43 +++++++++++++++
 build/UserALEWebExtension/options.js     | 43 +++++++++++++++
 build/packageLogs.d.ts                   | 13 +++++
 build/userale-2.4.0.js                   | 43 +++++++++++++++
 build/userale-2.4.0.js.map               |  2 +-
 build/userale-2.4.0.min.js               |  2 +-
 example/log-attribute-example/README.md  | 95 --------------------------------
 example/log-attribute-example/index.html | 82 ---------------------------
 example/log.schema.json                  |  2 +-
 src/packageLogs.ts                       | 45 +++++++++++++++
 test/e2e/spec/02-shared.spec.ts          |  7 ++-
 test/unit/spec/packageLogs.spec.ts       | 42 ++++++++++++++
 13 files changed, 279 insertions(+), 183 deletions(-)

diff --git a/build/UserALEWebExtension/background.js 
b/build/UserALEWebExtension/background.js
index 17746af..3b625d6 100644
--- a/build/UserALEWebExtension/background.js
+++ b/build/UserALEWebExtension/background.js
@@ -619,6 +619,8 @@ function packageLog(e, detailFcn) {
         sessionId: config$1.sessionId,
         httpSessionId: config$1.httpSessionId,
         browserSessionId: config$1.browserSessionId,
+        attributes: buildAttrs(e),
+        style: buildCSS(e),
     };
     for (const func of Object.values(cbHandlers)) {
         if (typeof func === "function") {
@@ -855,6 +857,47 @@ function detectBrowser() {
         version: browserInfo ? browserInfo.version : "",
     };
 }
+/**
+ * Builds an object containing attributes of an element.
+ * Attempts to parse all attribute values as JSON text.
+ * @param  {Event} e Event from which the target element's attributes should 
be extracted.
+ * @return {Record<string, any>} Object with element attributes as key-value 
pairs.
+ */
+function buildAttrs(e) {
+    const attributes = {};
+    const attributeBlackList = ["style"];
+    if (e.target && e.target instanceof Element) {
+        for (const attr of e.target.attributes) {
+            if (attributeBlackList.includes(attr.name))
+                continue;
+            let val = attr.value;
+            try {
+                val = JSON.parse(val);
+            }
+            catch (error) {
+                // Ignore parsing errors, fallback to raw string value
+            }
+            attributes[attr.name] = val;
+        }
+    }
+    return attributes;
+}
+/**
+ * Builds an object containing all CSS properties of an element.
+ * @param  {Event} e Event from which the target element's properties should 
be extracted.
+ * @return {Record<string, string>} Object with all CSS properties as 
key-value pairs.
+ */
+function buildCSS(e) {
+    const properties = {};
+    if (e.target && e.target instanceof HTMLElement) {
+        const styleObj = e.target.style;
+        for (let i = 0; i < styleObj.length; i++) {
+            const prop = styleObj[i];
+            properties[prop] = styleObj.getPropertyValue(prop);
+        }
+    }
+    return properties;
+}
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
diff --git a/build/UserALEWebExtension/content.js 
b/build/UserALEWebExtension/content.js
index 1709798..9696353 100644
--- a/build/UserALEWebExtension/content.js
+++ b/build/UserALEWebExtension/content.js
@@ -566,6 +566,8 @@ function packageLog(e, detailFcn) {
         sessionId: config$1.sessionId,
         httpSessionId: config$1.httpSessionId,
         browserSessionId: config$1.browserSessionId,
+        attributes: buildAttrs(e),
+        style: buildCSS(e),
     };
     for (const func of Object.values(cbHandlers)) {
         if (typeof func === "function") {
@@ -802,6 +804,47 @@ function detectBrowser() {
         version: browserInfo ? browserInfo.version : "",
     };
 }
+/**
+ * Builds an object containing attributes of an element.
+ * Attempts to parse all attribute values as JSON text.
+ * @param  {Event} e Event from which the target element's attributes should 
be extracted.
+ * @return {Record<string, any>} Object with element attributes as key-value 
pairs.
+ */
+function buildAttrs(e) {
+    const attributes = {};
+    const attributeBlackList = ["style"];
+    if (e.target && e.target instanceof Element) {
+        for (const attr of e.target.attributes) {
+            if (attributeBlackList.includes(attr.name))
+                continue;
+            let val = attr.value;
+            try {
+                val = JSON.parse(val);
+            }
+            catch (error) {
+                // Ignore parsing errors, fallback to raw string value
+            }
+            attributes[attr.name] = val;
+        }
+    }
+    return attributes;
+}
+/**
+ * Builds an object containing all CSS properties of an element.
+ * @param  {Event} e Event from which the target element's properties should 
be extracted.
+ * @return {Record<string, string>} Object with all CSS properties as 
key-value pairs.
+ */
+function buildCSS(e) {
+    const properties = {};
+    if (e.target && e.target instanceof HTMLElement) {
+        const styleObj = e.target.style;
+        for (let i = 0; i < styleObj.length; i++) {
+            const prop = styleObj[i];
+            properties[prop] = styleObj.getPropertyValue(prop);
+        }
+    }
+    return properties;
+}
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
diff --git a/build/UserALEWebExtension/options.js 
b/build/UserALEWebExtension/options.js
index fc8ef2c..91d7f82 100644
--- a/build/UserALEWebExtension/options.js
+++ b/build/UserALEWebExtension/options.js
@@ -566,6 +566,8 @@ function packageLog(e, detailFcn) {
         sessionId: config$1.sessionId,
         httpSessionId: config$1.httpSessionId,
         browserSessionId: config$1.browserSessionId,
+        attributes: buildAttrs(e),
+        style: buildCSS(e),
     };
     for (const func of Object.values(cbHandlers)) {
         if (typeof func === "function") {
@@ -802,6 +804,47 @@ function detectBrowser() {
         version: browserInfo ? browserInfo.version : "",
     };
 }
+/**
+ * Builds an object containing attributes of an element.
+ * Attempts to parse all attribute values as JSON text.
+ * @param  {Event} e Event from which the target element's attributes should 
be extracted.
+ * @return {Record<string, any>} Object with element attributes as key-value 
pairs.
+ */
+function buildAttrs(e) {
+    const attributes = {};
+    const attributeBlackList = ["style"];
+    if (e.target && e.target instanceof Element) {
+        for (const attr of e.target.attributes) {
+            if (attributeBlackList.includes(attr.name))
+                continue;
+            let val = attr.value;
+            try {
+                val = JSON.parse(val);
+            }
+            catch (error) {
+                // Ignore parsing errors, fallback to raw string value
+            }
+            attributes[attr.name] = val;
+        }
+    }
+    return attributes;
+}
+/**
+ * Builds an object containing all CSS properties of an element.
+ * @param  {Event} e Event from which the target element's properties should 
be extracted.
+ * @return {Record<string, string>} Object with all CSS properties as 
key-value pairs.
+ */
+function buildCSS(e) {
+    const properties = {};
+    if (e.target && e.target instanceof HTMLElement) {
+        const styleObj = e.target.style;
+        for (let i = 0; i < styleObj.length; i++) {
+            const prop = styleObj[i];
+            properties[prop] = styleObj.getPropertyValue(prop);
+        }
+    }
+    return properties;
+}
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
diff --git a/build/packageLogs.d.ts b/build/packageLogs.d.ts
index a34e759..b94fe8f 100644
--- a/build/packageLogs.d.ts
+++ b/build/packageLogs.d.ts
@@ -113,3 +113,16 @@ export declare function detectBrowser(): {
     browser: string;
     version: string | null;
 };
+/**
+ * Builds an object containing attributes of an element.
+ * Attempts to parse all attribute values as JSON text.
+ * @param  {Event} e Event from which the target element's attributes should 
be extracted.
+ * @return {Record<string, any>} Object with element attributes as key-value 
pairs.
+ */
+export declare function buildAttrs(e: Event): Record<string, any>;
+/**
+ * Builds an object containing all CSS properties of an element.
+ * @param  {Event} e Event from which the target element's properties should 
be extracted.
+ * @return {Record<string, string>} Object with all CSS properties as 
key-value pairs.
+ */
+export declare function buildCSS(e: Event): Record<string, string>;
diff --git a/build/userale-2.4.0.js b/build/userale-2.4.0.js
index ec004d6..8832057 100644
--- a/build/userale-2.4.0.js
+++ b/build/userale-2.4.0.js
@@ -577,6 +577,8 @@
           sessionId: config$1.sessionId,
           httpSessionId: config$1.httpSessionId,
           browserSessionId: config$1.browserSessionId,
+          attributes: buildAttrs(e),
+          style: buildCSS(e),
       };
       for (const func of Object.values(cbHandlers)) {
           if (typeof func === "function") {
@@ -813,6 +815,47 @@
           version: browserInfo ? browserInfo.version : "",
       };
   }
+  /**
+   * Builds an object containing attributes of an element.
+   * Attempts to parse all attribute values as JSON text.
+   * @param  {Event} e Event from which the target element's attributes should 
be extracted.
+   * @return {Record<string, any>} Object with element attributes as key-value 
pairs.
+   */
+  function buildAttrs(e) {
+      const attributes = {};
+      const attributeBlackList = ["style"];
+      if (e.target && e.target instanceof Element) {
+          for (const attr of e.target.attributes) {
+              if (attributeBlackList.includes(attr.name))
+                  continue;
+              let val = attr.value;
+              try {
+                  val = JSON.parse(val);
+              }
+              catch (error) {
+                  // Ignore parsing errors, fallback to raw string value
+              }
+              attributes[attr.name] = val;
+          }
+      }
+      return attributes;
+  }
+  /**
+   * Builds an object containing all CSS properties of an element.
+   * @param  {Event} e Event from which the target element's properties should 
be extracted.
+   * @return {Record<string, string>} Object with all CSS properties as 
key-value pairs.
+   */
+  function buildCSS(e) {
+      const properties = {};
+      if (e.target && e.target instanceof HTMLElement) {
+          const styleObj = e.target.style;
+          for (let i = 0; i < styleObj.length; i++) {
+              const prop = styleObj[i];
+              properties[prop] = styleObj.getPropertyValue(prop);
+          }
+      }
+      return properties;
+  }
 
   /*
    * Licensed to the Apache Software Foundation (ASF) under one or more
diff --git a/build/userale-2.4.0.js.map b/build/userale-2.4.0.js.map
index af6f712..206c070 100644
--- a/build/userale-2.4.0.js.map
+++ b/build/userale-2.4.0.js.map
@@ -1 +1 @@
-{"version":3,"file":"userale-2.4.0.js","sources":["../src/getInitialSettings.ts","../src/configure.ts","../node_modules/detect-browser/es/index.js","../src/packageLogs.ts","../src/attachHandlers.ts","../src/utils/auth/index.ts","../src/sendLogs.ts","../src/main.ts"],"sourcesContent":[null,null,"var
 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {\n  
  if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < 
l; i++) {\n        if (ar || !(i i [...]
\ No newline at end of file
+{"version":3,"file":"userale-2.4.0.js","sources":["../src/getInitialSettings.ts","../src/configure.ts","../node_modules/detect-browser/es/index.js","../src/packageLogs.ts","../src/attachHandlers.ts","../src/utils/auth/index.ts","../src/sendLogs.ts","../src/main.ts"],"sourcesContent":[null,null,"var
 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {\n  
  if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < 
l; i++) {\n        if (ar || !(i i [...]
\ No newline at end of file
diff --git a/build/userale-2.4.0.min.js b/build/userale-2.4.0.min.js
index 233c021..a5315f7 100644
--- a/build/userale-2.4.0.min.js
+++ b/build/userale-2.4.0.min.js
@@ -15,4 +15,4 @@
  * limitations under the License.
  * @preserved
  */
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof 
module?t(exports):"function"==typeof 
define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof 
globalThis?globalThis:e||self).userale={})}(this,(function(e){"use strict";var 
t="2.4.0";let n=null,o=null;function 
r(){null===n&&(n=i("userAlesessionId","session_"+String(Date.now()))),null===o&&(o=i("userAleHttpSessionId",function(){const
 e=new Uint8Array(16);return 
window.crypto.getRandomValues(e),Array.from(e,(e=>e.toStrin [...]
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof 
module?t(exports):"function"==typeof 
define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof 
globalThis?globalThis:e||self).userale={})}(this,(function(e){"use strict";var 
t="2.4.0";let n=null,o=null;function 
r(){null===n&&(n=i("userAlesessionId","session_"+String(Date.now()))),null===o&&(o=i("userAleHttpSessionId",function(){const
 e=new Uint8Array(16);return 
window.crypto.getRandomValues(e),Array.from(e,(e=>e.toStrin [...]
diff --git a/example/log-attribute-example/README.md 
b/example/log-attribute-example/README.md
deleted file mode 100644
index 8699d16..0000000
--- a/example/log-attribute-example/README.md
+++ /dev/null
@@ -1,95 +0,0 @@
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing,
-    software distributed under the License is distributed on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
--->
-# HTML attribute logging
-
-The following is an example outlining how to log HTML attributes with UserALE, 
and parse some common syntaxs found in attributes.
-
-## Common syntaxes
-
-Consider the following HTML canvas element. This element has a attribute, 
`data-name`, containing JSON data, `{"name" : "John Doe"}`, with special 
characters encoded for HTML. And another attribute, `style`, containing CSS 
formatted data.
-
-```html
-<div>
-  <canvas id="myCanvas" data-name="&#123;&#34;name&#34;&#58; &#34;John 
Doe&#34;&#125;" width="200" height="100" style="border:1px solid 
#000000;"></canvas>
-</div>
-```
-
-## Extracting and parsing attributes
-
-The following function shows how to extract attributes and parse JSON 
attribute values. The `style` attribute is excluded because it is handled as a 
special case in the next code block.
-
-```js
-
-/**
- * Builds an object containing attributes of an element.
- * Attempts to parse all attribute values as JSON text.
- * @param  {Object} e Event from which the target elemnet's attributes should 
be extracted from.
- * @return {Object} Object with element attributes as key value pairs.
- */
-function buildAttrs(e) {
-    let attributes = {};
-    let attributeBlackList = ["style"];
-    if(e.target && e.target instanceof Element) {
-        for(attr of e.target.attributes) {
-            if(attributeBlackList.includes(attr.name))
-                continue;
-            let val = attr.value;
-            try {
-                val = JSON.parse(val);
-            } catch (error) {}
-            attributes[attr.name] = val;
-        }
-    }
-    return attributes;
-}
-```
-
-The following function will parse the CSS found in the style attribute.
-
-```js
-/**
- * Builds an object containing all css properties of an element.
- * @param  {Object} e Event from which the target elemnet's properties should 
be extracted from.
- * @return {Object} Object with all CSS properties as key value pairs.
- */
-export function buildCSS(e) {
-    let properties = {};
-    if(e.target && e.target instanceof Element) {
-        let styleObj = e.target.style
-        for(prop of styleObj) {
-            properties[prop] = styleObj.getPropertyValue(prop);
-        }
-    }
-    return properties;
-}
-```
-The above functions can be used in the below snippet to add the results to 
each log message. In turn, this snippet can be added to a custom.js script to 
modify core UserALE behavior. See the 'index.js' example in this dir. 
-
-```js
-window.userale.addCallbacks({
-    map(log, e) {
-        return {
-            ...log,
-            attributes: buildAttrs(e),
-            style : buildCSS(e),
-            logType: 'custom',
-        };
-    }
-});
-```
\ No newline at end of file
diff --git a/example/log-attribute-example/index.html 
b/example/log-attribute-example/index.html
deleted file mode 100644
index 2c3da4f..0000000
--- a/example/log-attribute-example/index.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-  http://www.apache.org/licenses/LICENSE-2.0
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<html>
-<head>
-    <script
-            src="../../build/userale-2.4.0.min.js"
-            data-url=""
-            data-tool="Apache UserALE Example"
-            data-threshold="1"
-            data-interval="100"
-    ></script>
-</head>
-<body>
-<div class="new-feature-button">
-    <canvas id="myCanvas" data-name="&#123;&#34;name&#34;&#58; &#34;John 
Doe&#34;&#125;" width="200" height="100" style="border:1px solid #000000;">
-    </canvas>
-</div>
-</body>
-<script>
-    /**
-     * Builds an object containing attributes of an element.
-     * Attempts to parse all attribute values as JSON text.
-     * @param  {Object} e Event from which the target elemnet's attributes 
should be extracted from.
-     * @return {Object} Object with element attributes as key value pairs.
-     */
-    function buildAttrs(e) {
-    let attributes = {};
-    let attributeBlackList = ["style"];
-    if(e.target && e.target instanceof Element) {
-        for(attr of e.target.attributes) {
-        if(attributeBlackList.includes(attr.name))
-            continue;
-        let val = attr.value;
-        try {
-            val = JSON.parse(val);
-        } catch (error) {}
-        attributes[attr.name] = val;
-        }
-    }
-    return attributes;
-    }
-
-    /**
-     * Builds an object containing all css properties of an element.
-     * @param  {Object} e Event from which the target elemnet's properties 
should be extracted from.
-     * @return {Object} Object with all CSS properties as key value pairs.
-     */
-    export function buildCSS(e) {
-    let properties = {};
-    if(e.target && e.target instanceof Element) {
-        let styleObj = e.target.style
-        for(prop of styleObj) {
-        properties[prop] = styleObj.getPropertyValue(prop);
-        }
-    }
-        return properties;
-    }
-
-    window.userale.addCallbacks({
-        map(log, e) {
-            return {
-                ...log,
-                attributes: buildAttrs(e),
-                style : buildCSS(e),
-                logType: 'custom',
-            };
-        }
-    });
-</script>
-</html>
\ No newline at end of file
diff --git a/example/log.schema.json b/example/log.schema.json
index e98d282..83434b5 100644
--- a/example/log.schema.json
+++ b/example/log.schema.json
@@ -76,7 +76,7 @@
           "type": "boolean"
         },
         "details": {
-          "type": "object"
+          "type": ["object", "null"]
         },
         "userId": {
           "type": "string"
diff --git a/src/packageLogs.ts b/src/packageLogs.ts
index a3878d6..2cb0cbe 100644
--- a/src/packageLogs.ts
+++ b/src/packageLogs.ts
@@ -138,6 +138,8 @@ export function packageLog(
     sessionId: config.sessionId,
     httpSessionId: config.httpSessionId,
     browserSessionId: config.browserSessionId,
+    attributes: buildAttrs(e),
+    style: buildCSS(e),
   };
 
   if (typeof filterHandler === "function" && !filterHandler(log)) {
@@ -424,3 +426,46 @@ export function detectBrowser() {
     version: browserInfo ? browserInfo.version : "",
   };
 }
+
+/**
+ * Builds an object containing attributes of an element.
+ * Attempts to parse all attribute values as JSON text.
+ * @param  {Event} e Event from which the target element's attributes should 
be extracted.
+ * @return {Record<string, any>} Object with element attributes as key-value 
pairs.
+ */
+export function buildAttrs(e: Event): Record<string, any> {
+  const attributes: Record<string, any> = {};
+  const attributeBlackList = ["style"];
+
+  if (e.target && e.target instanceof Element) {
+    for (const attr of e.target.attributes) {
+      if (attributeBlackList.includes(attr.name)) continue;
+      let val: any = attr.value;
+      try {
+        val = JSON.parse(val);
+      } catch (error) {
+        // Ignore parsing errors, fallback to raw string value
+      }
+      attributes[attr.name] = val;
+    }
+  }
+
+  return attributes;
+}
+
+/**
+ * Builds an object containing all CSS properties of an element.
+ * @param  {Event} e Event from which the target element's properties should 
be extracted.
+ * @return {Record<string, string>} Object with all CSS properties as 
key-value pairs.
+ */
+export function buildCSS(e: Event): Record<string, string> {
+  const properties: Record<string, string> = {};
+  if (e.target && e.target instanceof HTMLElement) {
+    const styleObj = e.target.style;
+    for (let i = 0; i < styleObj.length; i++) {
+      const prop = styleObj[i];
+      properties[prop] = styleObj.getPropertyValue(prop);
+    }
+  }
+  return properties;
+}
diff --git a/test/e2e/spec/02-shared.spec.ts b/test/e2e/spec/02-shared.spec.ts
index ebaa4d5..eb65102 100644
--- a/test/e2e/spec/02-shared.spec.ts
+++ b/test/e2e/spec/02-shared.spec.ts
@@ -82,12 +82,13 @@ test.describe("Userale logging", () => {
     }
     const request = await requestPromise;
     const body = await request.postDataJSON();
-    console.log(body);
 
     var schema = require("../../../example/log.schema.json");
     for (const log of body) {
-      const result = validate(log, schema);
-      expect(result.valid).toBe(true);
+      if (log.logType == "raw" || log.logType == "custom") {
+        const result = validate(log, schema);
+        expect(result.valid).toBe(true);
+      }
     }
   });
 });
diff --git a/test/unit/spec/packageLogs.spec.ts 
b/test/unit/spec/packageLogs.spec.ts
index f827ab4..3de5fc0 100644
--- a/test/unit/spec/packageLogs.spec.ts
+++ b/test/unit/spec/packageLogs.spec.ts
@@ -29,6 +29,8 @@ import {
   packageLog,
   removeCallbacks,
   selectorizePath,
+  buildAttrs,
+  buildCSS,
 } from "@/packageLogs";
 import type { Logging } from "@/types";
 
@@ -381,4 +383,44 @@ describe("packageLogs", () => {
       expect(actualPath).toEqual(expectedPath);
     });
   });
+
+  test("buildAttrs", () => {
+    let result;
+    const document = window.document;
+    const ele = document.createElement("div");
+    const evt = new window.Event("CustomEvent", {
+      bubbles: true,
+      cancelable: true,
+    });
+    ele.setAttribute("data-json", '{"key": "value"}');
+    ele.setAttribute("data-string", "hello");
+    ele.setAttribute("style", "color: red;");
+    document.body.appendChild(ele);
+    ele.addEventListener("CustomEvent", (e) => (result = buildAttrs(e)));
+    ele.dispatchEvent(evt);
+    expect(result).toEqual({
+      "data-json": { key: "value" },
+      "data-string": "hello",
+    });
+    expect(result).not.toHaveProperty("style");
+  });
+
+  test("buildCSS", () => {
+    let result;
+    const document = window.document;
+    const ele = document.createElement("div");
+    const evt = new window.Event("CustomEvent", {
+      bubbles: true,
+      cancelable: true,
+    });
+    ele.style.color = "red";
+    ele.style.marginTop = "10px";
+    document.body.appendChild(ele);
+    ele.addEventListener("CustomEvent", (e) => (result = buildCSS(e)));
+    ele.dispatchEvent(evt);
+    expect(result).toEqual({
+      color: "red",
+      "margin-top": "10px",
+    });
+  });
 });

Reply via email to