Repository: capricorn86/happy-dom
Pull request #304 (2021-11-16 00:19:42)

Task/303 cssstylesheet insertrule should return the index of the newly inserted rule


Patch:
diff --git a/packages/happy-dom/src/css/CSSStyleSheet.ts b/packages/happy-dom/src/css/CSSStyleSheet.ts
index 59372c2b..2396b31a 100644
--- a/packages/happy-dom/src/css/CSSStyleSheet.ts
+++ b/packages/happy-dom/src/css/CSSStyleSheet.ts
@@ -1,9 +1,14 @@
+import DOMException from '../exception/DOMException';
+import DOMExceptionNameEnum from '../exception/DOMExceptionNameEnum';
 import CSSParser from './CSSParser';
 import CSSRule from './CSSRule';
 import MediaList from './MediaList';
 
 /**
  * Attr node interface.
+ *
+ * Reference:
+ * https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet.
  */
 export default class CSSStyleSheet {
 	public value: string = null;
@@ -51,15 +56,39 @@ export default class CSSStyleSheet {
 	 *
 	 * @param rule Rule.
 	 * @param [index] Index.
+	 * @returns The newly inserterted rule's index.
 	 */
-	public insertRule(rule: string, index?: number): void {
+	public insertRule(rule: string, index?: number): number {
 		const rules = CSSParser.parseFromString(this, rule);
 
+		if (rules.length === 0) {
+			throw new DOMException('Invalid CSS rule.', DOMExceptionNameEnum.hierarchyRequestError);
+		}
+
+		if (rules.length > 1) {
+			throw new DOMException(
+				'Only one rule is allowed to be added.',
+				DOMExceptionNameEnum.syntaxError
+			);
+		}
+
 		if (index !== undefined) {
-			this.cssRules.splice(index, 0, ...rules);
-		} else {
-			this.cssRules.push(...rules);
+			if (index > this.cssRules.length) {
+				throw new DOMException(
+					'Index is more than the length of CSSRuleList.',
+					DOMExceptionNameEnum.indexSizeError
+				);
+			}
+			this.cssRules.splice(index, 0);
+			this.cssRules.push(rules[0]);
+			return index;
 		}
+
+		const newIndex = this.cssRules.length;
+
+		this.cssRules.push(rules[0]);
+
+		return newIndex;
 	}
 
 	/**
diff --git a/packages/happy-dom/src/exception/DOMExceptionNameEnum.ts b/packages/happy-dom/src/exception/DOMExceptionNameEnum.ts
index 9b2fd859..04e773d7 100644
--- a/packages/happy-dom/src/exception/DOMExceptionNameEnum.ts
+++ b/packages/happy-dom/src/exception/DOMExceptionNameEnum.ts
@@ -1,4 +1,7 @@
 enum DOMExceptionNameEnum {
-	invalidStateError = 'InvalidStateError'
+	invalidStateError = 'InvalidStateError',
+	indexSizeError = 'IndexSizeError',
+	syntaxError = 'SyntaxError',
+	hierarchyRequestError = 'HierarchyRequestError'
 }
 export default DOMExceptionNameEnum;


Test patch:
diff --git a/packages/happy-dom/test/css/CSSStyleSheet.test.ts b/packages/happy-dom/test/css/CSSStyleSheet.test.ts
new file mode 100644
index 00000000..5aec1609
--- /dev/null
+++ b/packages/happy-dom/test/css/CSSStyleSheet.test.ts
@@ -0,0 +1,55 @@
+import DOMException from '../../src/exception/DOMException';
+import DOMExceptionNameEnum from '../../src/exception/DOMExceptionNameEnum';
+import CSSStyleSheet from '../../src/css/CSSStyleSheet';
+
+describe('CSSStyleSheet', () => {
+	let cssStyleSheet: CSSStyleSheet = null;
+
+	beforeEach(() => {
+		cssStyleSheet = new CSSStyleSheet();
+	});
+
+	describe('insertRule()', () => {
+		it('Inserts a rule at an index.', () => {
+			cssStyleSheet.insertRule('div { background-color: green }');
+			cssStyleSheet.insertRule('span { background-color: green }');
+			expect(cssStyleSheet.insertRule('button { background-color: green }', 1)).toBe(1);
+		});
+
+		it('Inserts a rule.', () => {
+			cssStyleSheet.insertRule('div { background-color: green }');
+			expect(cssStyleSheet.insertRule('span { background-color: green }')).toBe(1);
+		});
+
+		it('Throws error when a rule with invalid CSS is inserted.', () => {
+			expect(() => {
+				cssStyleSheet.insertRule('background-color: green');
+			}).toThrowError(
+				new DOMException('Invalid CSS rule.', DOMExceptionNameEnum.hierarchyRequestError)
+			);
+		});
+
+		it('Throws error when attempting to add more than one rule.', () => {
+			expect(() => {
+				cssStyleSheet.insertRule(
+					'div { background-color: green } span { background-color: green }'
+				);
+			}).toThrowError(
+				new DOMException('Only one rule is allowed to be added.', DOMExceptionNameEnum.syntaxError)
+			);
+		});
+
+		it('Throws error if index is more than the length of the CSS rule list.', () => {
+			cssStyleSheet.insertRule('div { background-color: green }');
+
+			expect(() => {
+				cssStyleSheet.insertRule('button { background-color: green }', 2);
+			}).toThrowError(
+				new DOMException(
+					'Index is more than the length of CSSRuleList.',
+					DOMExceptionNameEnum.indexSizeError
+				)
+			);
+		});
+	});
+});