Skip to content
This repository has been archived by the owner on Sep 26, 2024. It is now read-only.

MOC-294 flag for recording styles #193

Merged
merged 4 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions packages/reactor/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,15 @@ export interface AppliedModifications {
setHighlight(highlight: boolean): void;
}

export interface DomJsonExportNode {
export type DomJsonExportOptions = {
styles?: boolean;
}

export type DomJsonExportNode = {
tag: string;
visible: boolean;
text?: string;
attributes?: Record<string, string>;
attributes: Record<string, string>;
children?: DomJsonExportNode[];
Comment on lines +44 to 49
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Issues Found with DomJsonExportNode Type Changes

The recent change making the attributes property required in DomJsonExportNode introduces inconsistencies in the codebase. Specifically, the following instance is missing the attributes property:

  • File: packages/reactor/main.ts
    • Location: nodeToJson function
    • Issue: The DomJsonExportNode object is created without the attributes property.

Please update the affected code to include the attributes property to ensure consistency and prevent potential runtime errors.

🔗 Analysis chain

LGTM! Verify impact on existing code.

The change to make attributes a required property in DomJsonExportNode is logical and aligns with the typical structure of DOM nodes. This ensures consistency in the exported JSON representation of DOM nodes.

However, this change might affect existing code that uses this type. Please run the following script to verify the impact:

Ensure that all usage of DomJsonExportNode includes the attributes property, and update any code that might assume attributes is optional.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usage of DomJsonExportNode type and potential issues with the attributes property

# Test 1: Find all occurrences of DomJsonExportNode
echo "Occurrences of DomJsonExportNode:"
rg --type typescript "DomJsonExportNode"

# Test 2: Check for potential issues where attributes might be undefined
echo "\nPotential issues with attributes property:"
rg --type typescript "DomJsonExportNode.*\{(?!.*attributes)" -A 5

Length of output: 581


Script:

#!/bin/bash
# Description: Check for usage of DomJsonExportNode type and potential issues with the attributes property

# Test 1: Find all occurrences of DomJsonExportNode
echo "Occurrences of DomJsonExportNode:"
rg "DomJsonExportNode"

# Test 2: Check for potential issues where attributes might be undefined without using look-around
echo "\nPotential issues with attributes property:"
rg "DomJsonExportNode\s*{\s*(?!.*attributes)" -A 5 --pcre2

Length of output: 1669

}

Expand Down
41 changes: 39 additions & 2 deletions packages/reactor/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
AppliedModifications,
DomJsonExportNode,
DomJsonExportOptions,
ModificationRequest,
} from "./interfaces.js";
import { generateModifications } from "./modifications.js";
Expand Down Expand Up @@ -39,7 +40,11 @@ export async function modifyDom(
}
}

export const htmlElementToJson = (root: HTMLElement): DomJsonExportNode[] => {
export const htmlElementToJson = (root: HTMLElement, options?: DomJsonExportOptions): DomJsonExportNode[] => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

htmlElementToJson is used outside of browser contexts

Using htmlElementToJson without ensuring window is available can lead to runtime errors in non-browser environments.

Affected file:

  • packages/reactor/reactor.ts
🔗 Analysis chain

Ensure window is available in the execution environment

The use of window.getComputedStyle relies on the availability of the window object. Please verify that this function is always executed in a browser environment. If the code can run in non-browser environments (like Node.js), this will cause a runtime error.

You can run the following script to check for non-browser usages of htmlElementToJson:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find usages of 'htmlElementToJson' outside browser contexts.

# Search for files importing 'htmlElementToJson' that don't reference 'window'.
rg --type ts --files-with-matches 'htmlElementToJson' | xargs grep -L 'window'

Length of output: 104

const stylesMap: {[key: string]: string} = {};
const styleIndex: { idx: number } = { idx: 1 };
const exportStyles = options?.styles ?? false;

function nodeToJson(node: Node): DomJsonExportNode {
if (node instanceof Text) {
return {
Expand All @@ -49,6 +54,7 @@ export const htmlElementToJson = (root: HTMLElement): DomJsonExportNode[] => {
node.parentElement.offsetHeight > 0
: false,
text: node.data,
attributes: {}
};
}

Expand All @@ -60,15 +66,36 @@ export const htmlElementToJson = (root: HTMLElement): DomJsonExportNode[] => {
element instanceof HTMLElement
? element.offsetWidth > 0 || element.offsetHeight > 0
: false,
attributes: {},
};

if (element.attributes.length > 0) {
obj.attributes = {};
for (const attr of Array.from(element.attributes)) {
obj.attributes[attr.name] = attr.value;
}
}

if (exportStyles) {
const styles = window.getComputedStyle(element);
if (styles.length > 0) {
const styleString = Array.from(styles)
.map((style) => `${style}: ${styles.getPropertyValue(style)}`)
.join('; ');
let styleClass = stylesMap[styleString];
if (!styleClass) {
styleClass = `mocksi-${styleIndex.idx}`;
stylesMap[styleString] = styleClass;
styleIndex.idx += 1;
}

if (obj.attributes['class']) {
obj.attributes['class'] += ' ' + styleClass;
} else {
obj.attributes['class'] = styleClass;
}
Comment on lines +91 to +95
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle existing class attributes safely

When appending the new style class to the element's class attribute, ensure that you're correctly handling existing classes and avoiding potential duplicates.

Apply this diff to improve class attribute handling:

- if (obj.attributes['class']) {
-   obj.attributes['class'] += ' ' + styleClass;
- } else {
-   obj.attributes['class'] = styleClass;
- }
+ const existingClass = obj.attributes['class'] || '';
+ const classes = new Set(existingClass.split(/\s+/).filter(Boolean));
+ classes.add(styleClass);
+ obj.attributes['class'] = Array.from(classes).join(' ');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (obj.attributes['class']) {
obj.attributes['class'] += ' ' + styleClass;
} else {
obj.attributes['class'] = styleClass;
}
const existingClass = obj.attributes['class'] || '';
const classes = new Set(existingClass.split(/\s+/).filter(Boolean));
classes.add(styleClass);
obj.attributes['class'] = Array.from(classes).join(' ');

}
}
Comment on lines +78 to +97
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Optimize style extraction for performance

Using window.getComputedStyle for every element can be performance-intensive, especially for large DOM trees. Consider limiting the extracted styles to only those necessary for your application or implementing caching mechanisms.


const children = Array.from(element.childNodes).filter(textElementFilter);

// special case: if the element has only one child, and that child is a text node, then
Expand Down Expand Up @@ -101,6 +128,16 @@ export const htmlElementToJson = (root: HTMLElement): DomJsonExportNode[] => {
.filter(textElementFilter)
.map((child) => nodeToJson(child));

if (exportStyles) {
const stylesString = Object.entries(stylesMap).map(([styleString, clazz]) => `.${clazz} { ${styleString} }`).join('\n');
json.push({
tag: 'style',
visible: false,
text: stylesString,
attributes: {}
})
}
Comment on lines +131 to +139
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid adding empty <style> nodes

If no styles are collected (i.e., stylesMap is empty), the code still adds an empty <style> node to the JSON. This can be unnecessary and may introduce empty nodes in your output.

Apply this diff to add a check before adding the <style> node:

if (exportStyles && Object.keys(stylesMap).length > 0) {
  const stylesString = Object.entries(stylesMap)
    .map(([styleString, clazz]) => `.${clazz} { ${styleString} }`)
    .join('\n');
  json.push({
    tag: 'style',
    visible: false,
    text: stylesString,
    attributes: {}
  });
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (exportStyles) {
const stylesString = Object.entries(stylesMap).map(([styleString, clazz]) => `.${clazz} { ${styleString} }`).join('\n');
json.push({
tag: 'style',
visible: false,
text: stylesString,
attributes: {}
})
}
if (exportStyles && Object.keys(stylesMap).length > 0) {
const stylesString = Object.entries(stylesMap).map(([styleString, clazz]) => `.${clazz} { ${styleString} }`).join('\n');
json.push({
tag: 'style',
visible: false,
text: stylesString,
attributes: {}
});
}


return json;
};

Expand Down
5 changes: 3 additions & 2 deletions packages/reactor/reactor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
AppliedModifications,
DomJsonExportNode,
DomJsonExportOptions,
Highlighter,
ModificationRequest,
} from "./interfaces.js";
Expand Down Expand Up @@ -122,7 +123,7 @@ class Reactor {
* @throws {Error} If the reactor is not attached and no element is specified.
* @return {DomJsonExportNode[]} An array of `DomJsonExportNode` objects representing the exported DOM.
*/
exportDOM(element: null | HTMLElement = null): DomJsonExportNode[] {
exportDOM(element: null | HTMLElement = null, options?: DomJsonExportOptions): DomJsonExportNode[] {
let useElement = element;

if (!useElement) {
Expand All @@ -133,7 +134,7 @@ class Reactor {
}
}

return htmlElementToJson(useElement);
return htmlElementToJson(useElement, options);
}

/**
Expand Down
121 changes: 113 additions & 8 deletions packages/reactor/tests/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { JSDOM } from "jsdom";
import { describe, expect, it } from "vitest";
import { describe, expect, it, beforeEach } from "vitest";
import type { ModificationRequest } from "../interfaces";
import { modifyDom, modifyHtml } from "../main";
import { modifyDom, modifyHtml, htmlElementToJson } from "../main";
import type { AppliedModificationsImpl } from "../modifications";

// Set up a mock DOM environment
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
global.document = dom.window.document;
// biome-ignore lint/suspicious/noExplicitAny: testing
global.window = dom.window as any;

describe("modifyHtml", () => {
let doc: Document;

// Vitest beforeEach function for setup
beforeEach(() => {
doc = window.document.implementation.createHTMLDocument("Test Document");
});
Comment on lines +10 to +13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Ensure consistent use of doc in tests

Initialize doc consistently in all test cases. Alternatively, consider moving doc initialization within each test to avoid shared state.


it("should replace text content", async () => {
const html = `<div id="user-info">Eliza Hart</div>`;
const userRequest = JSON.stringify({
Expand Down Expand Up @@ -330,4 +331,108 @@ describe("modifyHtml", () => {
expect(result).not.toContain("<p>New content</p>");
expect(result).toContain("<p>Old content</p>");
});

it('should convert a simple HTML element to JSON', async () => {
doc.body.innerHTML = '<div id="test" class="example">Hello World!</div>';
const json = htmlElementToJson(doc.body);

expect(json).toEqual([
{
tag: 'div',
visible: false,
attributes: {
id: 'test',
class: 'example',
},
text: 'Hello World!',
},
]);
});
Comment on lines +335 to +350
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Unnecessary 'async' keyword in test function declaration

The test function is declared as async, but it does not use the await keyword inside. Consider removing async for clarity.

Apply this diff to remove the async keyword:

-	it('should convert a simple HTML element to JSON', async () => {
+	it('should convert a simple HTML element to JSON', () => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should convert a simple HTML element to JSON', async () => {
doc.body.innerHTML = '<div id="test" class="example">Hello World!</div>';
const json = htmlElementToJson(doc.body);
expect(json).toEqual([
{
tag: 'div',
visible: false,
attributes: {
id: 'test',
class: 'example',
},
text: 'Hello World!',
},
]);
});
it('should convert a simple HTML element to JSON', () => {
doc.body.innerHTML = '<div id="test" class="example">Hello World!</div>';
const json = htmlElementToJson(doc.body);
expect(json).toEqual([
{
tag: 'div',
visible: false,
attributes: {
id: 'test',
class: 'example',
},
text: 'Hello World!',
},
]);
});


it('should handle nested HTML elements', async () => {
doc.body.innerHTML = '<div id="test"><p>Hello</p><span>World!</span></div>';
const json = htmlElementToJson(doc.body);

expect(json).toEqual([
{
tag: 'div',
visible: false,
attributes: {
id: 'test',
},
children: [
{
attributes: {},
tag: 'p',
visible: false,
text: 'Hello',
},
{
attributes: {},
tag: 'span',
visible: false,
text: 'World!',
},
],
},
]);
});
Comment on lines +352 to +379
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Unnecessary 'async' keyword in test function declaration

Similar to the previous test, this function does not use await. Removing async improves readability.

Apply this diff:

-	it('should handle nested HTML elements', async () => {
+	it('should handle nested HTML elements', () => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should handle nested HTML elements', async () => {
doc.body.innerHTML = '<div id="test"><p>Hello</p><span>World!</span></div>';
const json = htmlElementToJson(doc.body);
expect(json).toEqual([
{
tag: 'div',
visible: false,
attributes: {
id: 'test',
},
children: [
{
attributes: {},
tag: 'p',
visible: false,
text: 'Hello',
},
{
attributes: {},
tag: 'span',
visible: false,
text: 'World!',
},
],
},
]);
});
it('should handle nested HTML elements', () => {
doc.body.innerHTML = '<div id="test"><p>Hello</p><span>World!</span></div>';
const json = htmlElementToJson(doc.body);
expect(json).toEqual([
{
tag: 'div',
visible: false,
attributes: {
id: 'test',
},
children: [
{
attributes: {},
tag: 'p',
visible: false,
text: 'Hello',
},
{
attributes: {},
tag: 'span',
visible: false,
text: 'World!',
},
],
},
]);
});


it('should export styles when the option is set', async () => {
doc.body.innerHTML = '<div id="test" style="color: red; font-size: 24px;">Hello World!</div>';
const json = htmlElementToJson(doc.body, {styles: true});

expect(json).toEqual([
{
tag: 'div',
visible: false,
attributes: {
class: 'mocksi-1',
id: 'test',
style: 'color: red; font-size: 24px;',
},
Comment on lines +391 to +393
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Redundant style attribute when styles are consolidated

When styles are consolidated into classes, retaining the inline style attribute may cause redundancy. Consider removing the style attribute from the elements to prevent duplication.

Apply this diff to remove the style attribute:

 attributes: {
-  class: 'mocksi-1',
-  id: 'test',
-  style: 'color: red; font-size: 24px;',
+  class: 'mocksi-1',
+  id: 'test',
 },

Also applies to: 415-417

text: 'Hello World!',
},
{
attributes: {},
tag: "style",
text: ".mocksi-1 { display: block; color: rgb(255, 0, 0); font-size: 24px; visibility: visible; pointer-events: auto; background-color: rgba(0, 0, 0, 0); border-block-start-color: rgb(255, 0, 0); border-block-end-color: rgb(255, 0, 0); border-inline-start-color: rgb(255, 0, 0); border-inline-end-color: rgb(255, 0, 0); border-top-color: rgb(255, 0, 0); border-right-color: rgb(255, 0, 0); border-bottom-color: rgb(255, 0, 0); border-left-color: rgb(255, 0, 0); caret-color: auto }",
visible: false
}
]);
});
Comment on lines +381 to +403
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Unnecessary 'async' keyword in test function declaration

The async keyword is unnecessary here as well.

Apply this diff:

-	it('should export styles when the option is set', async () => {
+	it('should export styles when the option is set', () => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should export styles when the option is set', async () => {
doc.body.innerHTML = '<div id="test" style="color: red; font-size: 24px;">Hello World!</div>';
const json = htmlElementToJson(doc.body, {styles: true});
expect(json).toEqual([
{
tag: 'div',
visible: false,
attributes: {
class: 'mocksi-1',
id: 'test',
style: 'color: red; font-size: 24px;',
},
text: 'Hello World!',
},
{
attributes: {},
tag: "style",
text: ".mocksi-1 { display: block; color: rgb(255, 0, 0); font-size: 24px; visibility: visible; pointer-events: auto; background-color: rgba(0, 0, 0, 0); border-block-start-color: rgb(255, 0, 0); border-block-end-color: rgb(255, 0, 0); border-inline-start-color: rgb(255, 0, 0); border-inline-end-color: rgb(255, 0, 0); border-top-color: rgb(255, 0, 0); border-right-color: rgb(255, 0, 0); border-bottom-color: rgb(255, 0, 0); border-left-color: rgb(255, 0, 0); caret-color: auto }",
visible: false
}
]);
});
it('should export styles when the option is set', () => {
doc.body.innerHTML = '<div id="test" style="color: red; font-size: 24px;">Hello World!</div>';
const json = htmlElementToJson(doc.body, {styles: true});
expect(json).toEqual([
{
tag: 'div',
visible: false,
attributes: {
class: 'mocksi-1',
id: 'test',
style: 'color: red; font-size: 24px;',
},
text: 'Hello World!',
},
{
attributes: {},
tag: "style",
text: ".mocksi-1 { display: block; color: rgb(255, 0, 0); font-size: 24px; visibility: visible; pointer-events: auto; background-color: rgba(0, 0, 0, 0); border-block-start-color: rgb(255, 0, 0); border-block-end-color: rgb(255, 0, 0); border-inline-start-color: rgb(255, 0, 0); border-inline-end-color: rgb(255, 0, 0); border-top-color: rgb(255, 0, 0); border-right-color: rgb(255, 0, 0); border-bottom-color: rgb(255, 0, 0); border-left-color: rgb(255, 0, 0); caret-color: auto }",
visible: false
}
]);
});


it('should consolidate styles when they are the same', async () => {
doc.body.innerHTML = '<div id="test" style="color: red; font-size: 24px;">Hello World!</div><div id="test" style="color: red; font-size: 24px;">Hello World!</div>';
const json = htmlElementToJson(doc.body, {styles: true});
Comment on lines +406 to +407
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Duplicate id attributes in HTML elements

Both div elements have the same id="test", which violates HTML standards as id attributes should be unique within a document. This could lead to unexpected behavior during DOM manipulation.

Apply this diff to assign unique id values:

-	doc.body.innerHTML = '<div id="test" style="color: red; font-size: 24px;">Hello World!</div><div id="test" style="color: red; font-size: 24px;">Hello World!</div>';
+	doc.body.innerHTML = '<div id="test1" style="color: red; font-size: 24px;">Hello World!</div><div id="test2" style="color: red; font-size: 24px;">Hello World!</div>';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
doc.body.innerHTML = '<div id="test" style="color: red; font-size: 24px;">Hello World!</div><div id="test" style="color: red; font-size: 24px;">Hello World!</div>';
const json = htmlElementToJson(doc.body, {styles: true});
doc.body.innerHTML = '<div id="test1" style="color: red; font-size: 24px;">Hello World!</div><div id="test2" style="color: red; font-size: 24px;">Hello World!</div>';
const json = htmlElementToJson(doc.body, {styles: true});


expect(json).toEqual([
{
tag: 'div',
visible: false,
attributes: {
class: 'mocksi-1',
id: 'test',
style: 'color: red; font-size: 24px;',
},
text: 'Hello World!',
},
{
tag: 'div',
visible: false,
attributes: {
class: 'mocksi-1',
id: 'test',
style: 'color: red; font-size: 24px;',
},
text: 'Hello World!',
},
{
attributes: {},
tag: "style",
text: ".mocksi-1 { display: block; color: rgb(255, 0, 0); font-size: 24px; visibility: visible; pointer-events: auto; background-color: rgba(0, 0, 0, 0); border-block-start-color: rgb(255, 0, 0); border-block-end-color: rgb(255, 0, 0); border-inline-start-color: rgb(255, 0, 0); border-inline-end-color: rgb(255, 0, 0); border-top-color: rgb(255, 0, 0); border-right-color: rgb(255, 0, 0); border-bottom-color: rgb(255, 0, 0); border-left-color: rgb(255, 0, 0); caret-color: auto }",
visible: false
}
]);
});
Comment on lines +405 to +437
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Unnecessary 'async' keyword in test function declaration

Again, remove async since there's no await used in the function.

Apply this diff:

-	it('should consolidate styles when they are the same', async () => {
+	it('should consolidate styles when they are the same', () => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should consolidate styles when they are the same', async () => {
doc.body.innerHTML = '<div id="test" style="color: red; font-size: 24px;">Hello World!</div><div id="test" style="color: red; font-size: 24px;">Hello World!</div>';
const json = htmlElementToJson(doc.body, {styles: true});
expect(json).toEqual([
{
tag: 'div',
visible: false,
attributes: {
class: 'mocksi-1',
id: 'test',
style: 'color: red; font-size: 24px;',
},
text: 'Hello World!',
},
{
tag: 'div',
visible: false,
attributes: {
class: 'mocksi-1',
id: 'test',
style: 'color: red; font-size: 24px;',
},
text: 'Hello World!',
},
{
attributes: {},
tag: "style",
text: ".mocksi-1 { display: block; color: rgb(255, 0, 0); font-size: 24px; visibility: visible; pointer-events: auto; background-color: rgba(0, 0, 0, 0); border-block-start-color: rgb(255, 0, 0); border-block-end-color: rgb(255, 0, 0); border-inline-start-color: rgb(255, 0, 0); border-inline-end-color: rgb(255, 0, 0); border-top-color: rgb(255, 0, 0); border-right-color: rgb(255, 0, 0); border-bottom-color: rgb(255, 0, 0); border-left-color: rgb(255, 0, 0); caret-color: auto }",
visible: false
}
]);
});
it('should consolidate styles when they are the same', () => {
doc.body.innerHTML = '<div id="test" style="color: red; font-size: 24px;">Hello World!</div><div id="test" style="color: red; font-size: 24px;">Hello World!</div>';
const json = htmlElementToJson(doc.body, {styles: true});
expect(json).toEqual([
{
tag: 'div',
visible: false,
attributes: {
class: 'mocksi-1',
id: 'test',
style: 'color: red; font-size: 24px;',
},
text: 'Hello World!',
},
{
tag: 'div',
visible: false,
attributes: {
class: 'mocksi-1',
id: 'test',
style: 'color: red; font-size: 24px;',
},
text: 'Hello World!',
},
{
attributes: {},
tag: "style",
text: ".mocksi-1 { display: block; color: rgb(255, 0, 0); font-size: 24px; visibility: visible; pointer-events: auto; background-color: rgba(0, 0, 0, 0); border-block-start-color: rgb(255, 0, 0); border-block-end-color: rgb(255, 0, 0); border-inline-start-color: rgb(255, 0, 0); border-inline-end-color: rgb(255, 0, 0); border-top-color: rgb(255, 0, 0); border-right-color: rgb(255, 0, 0); border-bottom-color: rgb(255, 0, 0); border-left-color: rgb(255, 0, 0); caret-color: auto }",
visible: false
}
]);
});

});
Loading